From b434ea079009021f060e12bb00c36d1a6cafa8ff Mon Sep 17 00:00:00 2001 From: "bryner%netscape.com" Date: Wed, 8 Jan 2003 06:33:05 +0000 Subject: [PATCH] Merging changes from CHIMERA_M1_0_1_BRANCH. --- camino/Chimera.pbproj/project.pbxproj | 553 +++++++++-- .../English.lproj/Appearance.nib/info.nib | 4 +- .../English.lproj/Appearance.nib/objects.nib | Bin 14811 -> 0 bytes .../English.lproj/Navigation.nib/info.nib | 6 +- .../English.lproj/Navigation.nib/objects.nib | Bin 10392 -> 10394 bytes .../images/app/disclosureArrowDown.tiff | Bin 0 -> 1422 bytes .../images/app/disclosureArrowRight.tiff | Bin 0 -> 1422 bytes camino/resources/images/app/small_close.tiff | 0 .../BrowserWindow.nib/classes.nib | 2 + .../English.lproj/BrowserWindow.nib/info.nib | 10 +- .../BrowserWindow.nib/objects.nib | Bin 18739 -> 19032 bytes .../English.lproj/Keychain.nib/classes.nib | 14 + .../English.lproj/Keychain.nib/info.nib | 12 + .../English.lproj/Keychain.nib/objects.nib | 0 .../English.lproj/Localizable.strings | Bin 10732 -> 11962 bytes .../English.lproj/MainMenu.nib/classes.nib | 2 +- .../English.lproj/MainMenu.nib/info.nib | 10 +- .../English.lproj/MainMenu.nib/objects.nib | Bin 10741 -> 10767 bytes .../ProgressDialog.nib/classes.nib | 34 +- .../English.lproj/ProgressDialog.nib/info.nib | 10 +- .../ProgressDialog.nib/objects.nib | Bin 2233 -> 1508 bytes .../ProgressView.nib/classes.nib | 22 + .../English.lproj/ProgressView.nib/info.nib | 27 + .../ProgressView.nib/objects.nib | Bin 0 -> 6197 bytes .../English.lproj/alert.nib/info.nib | 8 +- .../English.lproj/alert.nib/objects.nib | Bin 14759 -> 0 bytes camino/src/application/AppComponents.mm | 33 +- camino/src/application/MainController.h | 11 +- camino/src/application/MainController.mm | 26 +- camino/src/application/nsStaticComponents.cpp | 106 ++- camino/src/bookmarks/BookmarksDataSource.mm | 2 +- camino/src/browser/BrowserTabView.mm | 1 + camino/src/browser/BrowserWindow.mm | 2 + camino/src/browser/BrowserWindowController.h | 15 +- camino/src/browser/BrowserWindowController.mm | 43 +- camino/src/browser/BrowserWrapper.mm | 12 +- camino/src/browser/ContentClickListener.mm | 3 +- camino/src/browser/KeychainService.h | 55 +- camino/src/browser/KeychainService.mm | 261 +++++- camino/src/browser/SiteIconProvider.mm | 2 +- camino/src/browser/nsAlertController.h | 4 - camino/src/browser/nsAlertController.mm | 13 - camino/src/download/ProgressDlgController.h | 95 +- camino/src/download/ProgressDlgController.mm | 668 +++++-------- camino/src/download/ProgressViewController.h | 105 +++ camino/src/download/ProgressViewController.mm | 544 +++++++++++ camino/src/download/SaveHeaderSniffer.h | 3 +- camino/src/download/SaveHeaderSniffer.mm | 25 +- camino/src/download/nsDownloadListener.h | 18 +- camino/src/download/nsDownloadListener.mm | 89 +- camino/src/embedding/CHBrowserService.mm | 9 - camino/src/embedding/CHBrowserView.h | 5 +- camino/src/embedding/CHBrowserView.mm | 14 +- .../src/embedding/CHDownloadProgressDisplay.h | 62 +- .../embedding/CHDownloadProgressDisplay.mm | 33 +- camino/src/extensions/CHStackView.h | 61 ++ camino/src/extensions/CHStackView.m | 143 +++ camino/src/extensions/NSView+Utils.h | 60 ++ camino/src/extensions/NSView+Utils.m | 154 +++ .../src/extensions/RDFOutlineViewDataSource.h | 36 +- .../extensions/RDFOutlineViewDataSource.mm | 377 ++++---- camino/src/history/HistoryDataSource.h | 16 +- camino/src/history/HistoryDataSource.mm | 166 ++-- camino/src/includes/ChimeraUIConstants.h | 10 + camino/src/preferences/PreferenceManager.h | 3 + camino/src/preferences/PreferenceManager.mm | 294 +++--- chimera/Chimera.pbproj/project.pbxproj | 553 +++++++++-- .../English.lproj/Appearance.nib/info.nib | 17 - .../English.lproj/Appearance.nib/objects.nib | Bin 14811 -> 0 bytes .../English.lproj/Navigation.nib/info.nib | 27 - .../English.lproj/Navigation.nib/objects.nib | Bin 10392 -> 0 bytes .../images/app/disclosureArrowDown.tiff | 0 .../images/app/disclosureArrowRight.tiff | 0 chimera/resources/images/app/small_close.tiff | 0 .../BrowserWindow.nib/classes.nib | 177 ---- .../English.lproj/BrowserWindow.nib/info.nib | 10 +- .../BrowserWindow.nib/objects.nib | Bin 18739 -> 19032 bytes .../English.lproj/Keychain.nib/classes.nib | 0 .../English.lproj/Keychain.nib/info.nib | 0 .../English.lproj/Keychain.nib/objects.nib | 0 .../English.lproj/Localizable.strings | Bin 10732 -> 11962 bytes .../English.lproj/MainMenu.nib/classes.nib | 2 +- .../English.lproj/MainMenu.nib/info.nib | 10 +- .../English.lproj/MainMenu.nib/objects.nib | Bin 10741 -> 10767 bytes .../ProgressDialog.nib/classes.nib | 19 - .../English.lproj/ProgressDialog.nib/info.nib | 12 - .../ProgressDialog.nib/objects.nib | Bin 2233 -> 0 bytes .../ProgressView.nib/classes.nib | 0 .../English.lproj/ProgressView.nib/info.nib | 0 .../ProgressView.nib/objects.nib | 0 .../English.lproj/alert.nib/info.nib | 16 - .../English.lproj/alert.nib/objects.nib | Bin 14759 -> 0 bytes chimera/src/application/AppComponents.mm | 33 +- chimera/src/application/MainController.h | 11 +- chimera/src/application/MainController.mm | 26 +- .../src/application/nsStaticComponents.cpp | 106 ++- chimera/src/bookmarks/BookmarksDataSource.mm | 883 ------------------ chimera/src/browser/BrowserTabView.mm | 1 + chimera/src/browser/BrowserWindow.mm | 94 -- chimera/src/browser/BrowserWindowController.h | 15 +- .../src/browser/BrowserWindowController.mm | 43 +- chimera/src/browser/BrowserWrapper.mm | 12 +- chimera/src/browser/ContentClickListener.mm | 147 --- chimera/src/browser/KeychainService.h | 140 --- chimera/src/browser/KeychainService.mm | 261 +++++- chimera/src/browser/SiteIconProvider.mm | 344 ------- chimera/src/browser/nsAlertController.h | 4 - chimera/src/browser/nsAlertController.mm | 13 - chimera/src/download/ProgressDlgController.h | 86 -- chimera/src/download/ProgressDlgController.mm | 668 +++++-------- chimera/src/download/ProgressViewController.h | 0 .../src/download/ProgressViewController.mm | 544 +++++++++++ chimera/src/download/SaveHeaderSniffer.h | 84 -- chimera/src/download/SaveHeaderSniffer.mm | 25 +- chimera/src/download/nsDownloadListener.h | 93 -- chimera/src/download/nsDownloadListener.mm | 89 +- chimera/src/embedding/CHBrowserService.mm | 9 - chimera/src/embedding/CHBrowserView.h | 5 +- chimera/src/embedding/CHBrowserView.mm | 14 +- .../src/embedding/CHDownloadProgressDisplay.h | 167 ---- .../embedding/CHDownloadProgressDisplay.mm | 76 -- chimera/src/extensions/CHStackView.h | 0 chimera/src/extensions/CHStackView.m | 0 chimera/src/extensions/NSView+Utils.h | 0 chimera/src/extensions/NSView+Utils.m | 0 .../src/extensions/RDFOutlineViewDataSource.h | 36 +- .../extensions/RDFOutlineViewDataSource.mm | 377 ++++---- chimera/src/history/HistoryDataSource.h | 65 -- chimera/src/history/HistoryDataSource.mm | 166 ++-- chimera/src/includes/ChimeraUIConstants.h | 54 -- chimera/src/preferences/PreferenceManager.h | 72 -- chimera/src/preferences/PreferenceManager.mm | 294 +++--- 132 files changed, 5507 insertions(+), 4686 deletions(-) create mode 100644 camino/resources/images/app/disclosureArrowDown.tiff create mode 100644 camino/resources/images/app/disclosureArrowRight.tiff create mode 100644 camino/resources/images/app/small_close.tiff create mode 100644 camino/resources/localized/English.lproj/Keychain.nib/classes.nib create mode 100644 camino/resources/localized/English.lproj/Keychain.nib/info.nib create mode 100644 camino/resources/localized/English.lproj/Keychain.nib/objects.nib create mode 100644 camino/resources/localized/English.lproj/ProgressView.nib/classes.nib create mode 100644 camino/resources/localized/English.lproj/ProgressView.nib/info.nib create mode 100644 camino/resources/localized/English.lproj/ProgressView.nib/objects.nib create mode 100644 camino/src/download/ProgressViewController.h create mode 100644 camino/src/download/ProgressViewController.mm create mode 100644 camino/src/extensions/CHStackView.h create mode 100644 camino/src/extensions/CHStackView.m create mode 100644 camino/src/extensions/NSView+Utils.h create mode 100644 camino/src/extensions/NSView+Utils.m create mode 100644 chimera/resources/images/app/disclosureArrowDown.tiff create mode 100644 chimera/resources/images/app/disclosureArrowRight.tiff create mode 100644 chimera/resources/images/app/small_close.tiff create mode 100644 chimera/resources/localized/English.lproj/Keychain.nib/classes.nib create mode 100644 chimera/resources/localized/English.lproj/Keychain.nib/info.nib create mode 100644 chimera/resources/localized/English.lproj/Keychain.nib/objects.nib create mode 100644 chimera/resources/localized/English.lproj/ProgressView.nib/classes.nib create mode 100644 chimera/resources/localized/English.lproj/ProgressView.nib/info.nib create mode 100644 chimera/resources/localized/English.lproj/ProgressView.nib/objects.nib create mode 100644 chimera/src/download/ProgressViewController.h create mode 100644 chimera/src/download/ProgressViewController.mm create mode 100644 chimera/src/extensions/CHStackView.h create mode 100644 chimera/src/extensions/CHStackView.m create mode 100644 chimera/src/extensions/NSView+Utils.h create mode 100644 chimera/src/extensions/NSView+Utils.m diff --git a/camino/Chimera.pbproj/project.pbxproj b/camino/Chimera.pbproj/project.pbxproj index f789e40d443..7d26c0177ce 100644 --- a/camino/Chimera.pbproj/project.pbxproj +++ b/camino/Chimera.pbproj/project.pbxproj @@ -146,6 +146,7 @@ 4A9504CDFFE6A4B311CA0CBA, F593CA5E034EB88E01A967F3, ); + hasScannedForEncodings = 1; isa = PBXProject; knownRegions = ( English, @@ -200,6 +201,7 @@ refType = 4; }; 29B97316FDCFA39411CA2CEA = { + fileEncoding = 30; isa = PBXFileReference; name = main.m; path = src/application/main.m; @@ -495,7 +497,6 @@ "; - shouldUseHeadermap = 1; }; 29B97327FDCFA39411CA2CEA = { buildActionMask = 2147483647; @@ -541,7 +542,6 @@ F55C4DD402D2864E0130B065, F50D9DE402ECC2C601BB4219, F50D9DEF02EE0AB101BB4219, - F50D9DF302EE194001BB4219, F50D9DF702EE2B9B01BB4219, F5D33CBF02EF61AA01A967F3, F566BD1402EFA9AD01A967F3, @@ -565,6 +565,9 @@ F57BEDA003A1825001A9666E, F5C8D55303A2A42401A8016F, F5C8D55603A2A43301A8016F, + A7AEBEC603CB962500A967F8, + A7AEBEE003CB9CD700A967F8, + A7AEBEE903CB9DFB00A967F8, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -643,6 +646,12 @@ F5566DC5038E075F01A80166, F5566DC6038E075F01A80166, F5566DC7038E075F01A80166, + A7AEBED103CB9BD000A967F8, + A7AEBED203CB9BD000A967F8, + A7AEBED303CB9BD000A967F8, + A7AEBEDB03CB9C2F00A967F8, + A7AEBEDC03CB9C2F00A967F8, + A7F01A4903CBBCA500A967F8, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -689,7 +698,6 @@ F59236C302C89ACA0100012B, F50D9DE502ECC2C601BB4219, F50D9DF002EE0AB101BB4219, - F50D9DF402EE194001BB4219, F50D9DF802EE2B9B01BB4219, F5D33CC002EF61AA01A967F3, F5D33CC102EF61AA01A967F3, @@ -712,6 +720,9 @@ F55EBC9D0383665201A80166, F57BED9803A1824001A9666E, F57BED9F03A1825001A9666E, + A7AEBEC903CB964000A967F8, + A7AEBEE303CB9CEC00A967F8, + A7AEBEE603CB9DDF00A967F8, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -752,12 +763,14 @@ //2E3 //2E4 2E2939FF027F33604B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = PageProxyIcon.mm; path = src/browser/PageProxyIcon.mm; refType = 2; }; 2E293A00027F33604B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = PageProxyIcon.h; path = src/browser/PageProxyIcon.h; @@ -776,12 +789,14 @@ }; }; 2E748B72029A448D4B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = GoMenu.h; path = src/browser/GoMenu.h; refType = 2; }; 2E748B73029A448D4B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = GoMenu.mm; path = src/browser/GoMenu.mm; @@ -800,12 +815,14 @@ }; }; 2EEC3E61028138714B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksOutlineView.h; path = src/bookmarks/BookmarksOutlineView.h; refType = 2; }; 2EEC3E62028138714B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksOutlineView.mm; path = src/bookmarks/BookmarksOutlineView.mm; @@ -881,6 +898,292 @@ //982 //983 //984 +//A70 +//A71 +//A72 +//A73 +//A74 + A7AEBEB103CB950400A967F8 = { + isa = PBXFileReference; + name = xmlextras.xpt; + path = ../dist/Embed/components/xmlextras.xpt; + refType = 2; + }; + A7AEBEB303CB954500A967F8 = { + fileRef = A7AEBEB103CB950400A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEB403CB955700A967F8 = { + fileRef = A7AEBEB103CB950400A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC403CB962500A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = "NSView+Utils.h"; + path = "src/extensions/NSView+Utils.h"; + refType = 2; + }; + A7AEBEC503CB962500A967F8 = { + fileRef = A7AEBEC403CB962500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC603CB962500A967F8 = { + fileRef = A7AEBEC403CB962500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC703CB964000A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = "NSView+Utils.m"; + path = "src/extensions/NSView+Utils.m"; + refType = 2; + }; + A7AEBEC803CB964000A967F8 = { + fileRef = A7AEBEC703CB964000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC903CB964000A967F8 = { + fileRef = A7AEBEC703CB964000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECA03CB96D600A967F8 = { + isa = PBXFileReference; + name = nsProxyAutoConfig.js; + path = ../netwerk/base/src/nsProxyAutoConfig.js; + refType = 2; + }; + A7AEBECB03CB96E700A967F8 = { + fileRef = A7AEBECA03CB96D600A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECC03CB96F900A967F8 = { + fileRef = A7AEBECA03CB96D600A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECE03CB9BD000A967F8 = { + isa = PBXFileReference; + name = disclosureArrowDown.tiff; + path = resources/images/app/disclosureArrowDown.tiff; + refType = 2; + }; + A7AEBECF03CB9BD000A967F8 = { + isa = PBXFileReference; + name = disclosureArrowRight.tiff; + path = resources/images/app/disclosureArrowRight.tiff; + refType = 2; + }; + A7AEBED003CB9BD000A967F8 = { + isa = PBXFileReference; + name = small_close.tiff; + path = resources/images/app/small_close.tiff; + refType = 2; + }; + A7AEBED103CB9BD000A967F8 = { + fileRef = A7AEBECE03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED203CB9BD000A967F8 = { + fileRef = A7AEBECF03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED303CB9BD000A967F8 = { + fileRef = A7AEBED003CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED403CB9BD000A967F8 = { + fileRef = A7AEBECE03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED503CB9BD000A967F8 = { + fileRef = A7AEBECF03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED603CB9BD000A967F8 = { + fileRef = A7AEBED003CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED703CB9C2F00A967F8 = { + children = ( + A7AEBED803CB9C2F00A967F8, + ); + isa = PBXVariantGroup; + name = Keychain.nib; + path = ""; + refType = 2; + }; + A7AEBED803CB9C2F00A967F8 = { + isa = PBXFileReference; + name = English; + path = resources/localized/English.lproj/Keychain.nib; + refType = 4; + }; + A7AEBED903CB9C2F00A967F8 = { + children = ( + A7AEBEDA03CB9C2F00A967F8, + ); + isa = PBXVariantGroup; + name = ProgressView.nib; + path = ""; + refType = 2; + }; + A7AEBEDA03CB9C2F00A967F8 = { + isa = PBXFileReference; + name = English; + path = resources/localized/English.lproj/ProgressView.nib; + refType = 4; + }; + A7AEBEDB03CB9C2F00A967F8 = { + fileRef = A7AEBED703CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDC03CB9C2F00A967F8 = { + fileRef = A7AEBED903CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDD03CB9C2F00A967F8 = { + fileRef = A7AEBED703CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDE03CB9C2F00A967F8 = { + fileRef = A7AEBED903CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDF03CB9CD700A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = CHStackView.h; + path = src/extensions/CHStackView.h; + refType = 2; + }; + A7AEBEE003CB9CD700A967F8 = { + fileRef = A7AEBEDF03CB9CD700A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE103CB9CD700A967F8 = { + fileRef = A7AEBEDF03CB9CD700A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE203CB9CEC00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = CHStackView.m; + path = src/extensions/CHStackView.m; + refType = 2; + }; + A7AEBEE303CB9CEC00A967F8 = { + fileRef = A7AEBEE203CB9CEC00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE403CB9CEC00A967F8 = { + fileRef = A7AEBEE203CB9CEC00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE503CB9DDF00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ProgressViewController.mm; + path = src/download/ProgressViewController.mm; + refType = 2; + }; + A7AEBEE603CB9DDF00A967F8 = { + fileRef = A7AEBEE503CB9DDF00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE703CB9DDF00A967F8 = { + fileRef = A7AEBEE503CB9DDF00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE803CB9DFB00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ProgressViewController.h; + path = src/download/ProgressViewController.h; + refType = 2; + }; + A7AEBEE903CB9DFB00A967F8 = { + fileRef = A7AEBEE803CB9DFB00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEEA03CB9DFB00A967F8 = { + fileRef = A7AEBEE803CB9DFB00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7F01A4803CBBCA500A967F8 = { + isa = PBXBundleReference; + name = PrintPDE.plugin; + path = ../dist/PrintPDE.plugin; + refType = 2; + }; + A7F01A4903CBBCA500A967F8 = { + fileRef = A7F01A4803CBBCA500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7F01A4A03CBBCA500A967F8 = { + fileRef = A7F01A4803CBBCA500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; +//A70 +//A71 +//A72 +//A73 +//A74 //F50 //F51 //F52 @@ -1169,6 +1472,7 @@ }; }; F507BA480213AD5F01D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksService.h; path = src/bookmarks/BookmarksService.h; @@ -1181,6 +1485,7 @@ }; }; F507BA4C0213AFF701D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksService.mm; path = src/bookmarks/BookmarksService.mm; @@ -1224,6 +1529,7 @@ refType = 4; }; F507BA540213C29E01D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = bookmarks.xml; path = resources/application/bookmarks.xml; @@ -1243,18 +1549,23 @@ F540BD1C029ED17901026D5D, F5A112C902DF270F01026D5D, F55B6BF402EF1F7E01026D5D, + A7AEBECE03CB9BD000A967F8, + A7AEBECF03CB9BD000A967F8, + A7AEBED003CB9BD000A967F8, ); isa = PBXGroup; - name = Graphics; + name = images; refType = 4; }; F50D9DE202ECC2C601BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = nsDownloadListener.h; path = src/download/nsDownloadListener.h; refType = 2; }; F50D9DE302ECC2C601BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = nsDownloadListener.mm; path = src/download/nsDownloadListener.mm; @@ -1301,12 +1612,14 @@ }; }; F50D9DED02EE0AB101BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = CHDownloadProgressDisplay.h; path = src/embedding/CHDownloadProgressDisplay.h; refType = 2; }; F50D9DEE02EE0AB101BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = CHDownloadProgressDisplay.mm; path = src/embedding/CHDownloadProgressDisplay.mm; @@ -1324,37 +1637,15 @@ settings = { }; }; - F50D9DF102EE194001BB4219 = { - isa = PBXFileReference; - name = CHDownloadFactories.h; - path = src/embedding/CHDownloadFactories.h; - refType = 2; - }; - F50D9DF202EE194001BB4219 = { - isa = PBXFileReference; - name = CHDownloadFactories.mm; - path = src/embedding/CHDownloadFactories.mm; - refType = 2; - }; - F50D9DF302EE194001BB4219 = { - fileRef = F50D9DF102EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; - F50D9DF402EE194001BB4219 = { - fileRef = F50D9DF202EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F50D9DF502EE2B9A01BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = SaveHeaderSniffer.h; path = src/download/SaveHeaderSniffer.h; refType = 2; }; F50D9DF602EE2B9A01BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = SaveHeaderSniffer.mm; path = src/download/SaveHeaderSniffer.mm; @@ -1374,8 +1665,6 @@ }; F50D9DF902EE2C1D01BB4219 = { children = ( - F50D9DF102EE194001BB4219, - F50D9DF202EE194001BB4219, F50D9DED02EE0AB101BB4219, F50D9DEE02EE0AB101BB4219, ); @@ -1387,8 +1676,9 @@ children = ( F50D9DF502EE2B9A01BB4219, F50D9DF602EE2B9A01BB4219, - F517395B020CE3740189DA0C, F50D9DE302ECC2C601BB4219, + A7AEBEE503CB9DDF00A967F8, + F517395B020CE3740189DA0C, ); isa = PBXGroup; name = Chimera; @@ -1549,6 +1839,7 @@ }; }; F5125A110202064D01FAFD9F = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWrapper.h; path = src/browser/BrowserWrapper.h; @@ -1682,6 +1973,7 @@ }; }; F5137A1102676B9101026D05 = { + fileEncoding = 30; isa = PBXFileReference; name = Find.h; path = src/find/Find.h; @@ -1768,7 +2060,6 @@ "; - shouldUseHeadermap = 0; }; F51704D3034A305B01026D5D = { buildActionMask = 2147483647; @@ -1898,12 +2189,14 @@ refType = 2; }; F51704E9034A30DF01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityPane.h; path = PreferencePanes/Security/SecurityPane.h; refType = 2; }; F51704EA034A30DF01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityPane.mm; path = PreferencePanes/Security/SecurityPane.mm; @@ -2037,7 +2330,6 @@ "; - shouldUseHeadermap = 0; }; F51704FE034A38FD01026D5D = { buildActionMask = 2147483647; @@ -2169,12 +2461,14 @@ target = F51704FD034A38FD01026D5D; }; F5170515034A398F01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebFeatures.h; path = PreferencePanes/WebFeatures/WebFeatures.h; refType = 2; }; F5170516034A398F01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebFeatures.mm; path = PreferencePanes/WebFeatures/WebFeatures.mm; @@ -2253,6 +2547,7 @@ refType = 2; }; F5170530034B5E9701026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = English.lproj/Localizable.strings; @@ -2271,12 +2566,14 @@ refType = 2; }; F517395A020CE3740189DA0C = { + fileEncoding = 30; isa = PBXFileReference; name = ProgressDlgController.h; path = src/download/ProgressDlgController.h; refType = 2; }; F517395B020CE3740189DA0C = { + fileEncoding = 30; isa = PBXFileReference; name = ProgressDlgController.mm; path = src/download/ProgressDlgController.mm; @@ -2320,6 +2617,7 @@ }; F51842F30206168101A966FE = { children = ( + F5C8D55203A2A42401A8016F, F5F94B900332532801026D5D, F5DE10E60209DC0601A967DF, F517395A020CE3740189DA0C, @@ -2363,6 +2661,7 @@ F53D36BD037843C201A80166, F58DB2D20381FD3301A9666E, F5C8D55503A2A43301A8016F, + A7AEBEE803CB9DFB00A967F8, ); isa = PBXGroup; name = Headers; @@ -2400,12 +2699,14 @@ }; }; F51B70B6026EC98B01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = GetURLCommand.h; path = src/appleevents/GetURLCommand.h; refType = 2; }; F51B70B7026EC98B01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = GetURLCommand.mm; path = src/appleevents/GetURLCommand.mm; @@ -2747,7 +3048,6 @@ "; - shouldUseHeadermap = 0; }; F52627CF027E976B01000102 = { buildActionMask = 2147483647; @@ -2796,6 +3096,7 @@ runOnlyForDeploymentPostprocessing = 0; }; F52627D4027E982201000102 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = Navigation.h; @@ -2804,6 +3105,7 @@ tabWidth = 2; }; F52627D5027E982201000102 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = Navigation.mm; @@ -2989,6 +3291,7 @@ refType = 2; }; F528E218020FD8400168DE43 = { + fileEncoding = 30; isa = PBXFileReference; name = FindDlgController.h; path = src/find/FindDlgController.h; @@ -3001,6 +3304,7 @@ }; }; F528E21A020FD9620168DE43 = { + fileEncoding = 30; isa = PBXFileReference; name = FindDlgController.mm; path = src/find/FindDlgController.mm; @@ -3013,12 +3317,14 @@ }; }; F529788A0371820B01026DCE = { + fileEncoding = 30; isa = PBXFileReference; name = CHClickListener.h; path = src/embedding/CHClickListener.h; refType = 2; }; F529788B0371820B01026DCE = { + fileEncoding = 30; isa = PBXFileReference; name = CHClickListener.mm; path = src/embedding/CHClickListener.mm; @@ -3049,6 +3355,7 @@ }; }; F52CE65902BFA88701026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = resources/localized/English.lproj/Localizable.strings; @@ -3094,12 +3401,14 @@ }; }; F52D5CCF027A887001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteTextField.h; path = src/browser/AutoCompleteTextField.h; refType = 2; }; F52D5CD0027A887001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteTextField.mm; path = src/browser/AutoCompleteTextField.mm; @@ -3118,12 +3427,14 @@ }; }; F52D5CD3027A88C601A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteDataSource.h; path = src/browser/AutoCompleteDataSource.h; refType = 2; }; F52D5CD4027A88C601A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteDataSource.mm; path = src/browser/AutoCompleteDataSource.mm; @@ -3142,12 +3453,14 @@ }; }; F52D5CD7027D3D5001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = PreferenceManager.h; path = src/preferences/PreferenceManager.h; refType = 2; }; F52D5CD8027D3D5001A80166 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = PreferenceManager.mm; @@ -3203,24 +3516,28 @@ }; }; F52F87CB027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = HistoryDataSource; path = src/history/HistoryDataSource.h; refType = 2; }; F52F87CC027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = RDFOutlineViewDataSource.h; path = src/extensions/RDFOutlineViewDataSource.h; refType = 2; }; F52F87CD027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = HistoryDataSource.mm; path = src/history/HistoryDataSource.mm; refType = 4; }; F52F87CE027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = RDFOutlineViewDataSource.mm; path = src/extensions/RDFOutlineViewDataSource.mm; @@ -3251,6 +3568,7 @@ }; }; F53849040349779901A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = Localizable.strings; path = English.lproj/Localizable.strings; @@ -3343,12 +3661,14 @@ }; }; F53C1CD6032FF3B301A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserContentViews.h; path = src/browser/BrowserContentViews.h; refType = 2; }; F53C1CD7032FF3B301A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserContentViews.mm; path = src/browser/BrowserContentViews.mm; @@ -3379,12 +3699,14 @@ }; }; F53D36BA037843B801A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksMenu.mm; path = src/bookmarks/BookmarksMenu.mm; refType = 2; }; F53D36BD037843C201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksMenu.h; path = src/bookmarks/BookmarksMenu.h; @@ -3397,6 +3719,7 @@ }; }; F53E012902AEE91C01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarkInfoController.h; path = src/bookmarks/BookmarkInfoController.h; @@ -3415,6 +3738,7 @@ }; }; F53E012C02AEE93601A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarkInfoController.mm; path = src/bookmarks/BookmarkInfoController.mm; @@ -3471,54 +3795,63 @@ refType = 2; }; F53F21EC022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencePaneDefaults.plist; path = src/preferences/MVPreferencePaneDefaults.plist; refType = 2; }; F53F21ED022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencePaneGroups.plist; path = src/preferences/MVPreferencePaneGroups.plist; refType = 2; }; F53F21EE022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = resources/localized/English.lproj/MVPreferencePaneGroups.strings; refType = 2; }; F53F21EF022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesController.h; path = src/preferences/MVPreferencesController.h; refType = 2; }; F53F21F0022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesController.mm; path = src/preferences/MVPreferencesController.mm; refType = 2; }; F53F21F1022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesGroupedIconView.h; path = src/preferences/MVPreferencesGroupedIconView.h; refType = 2; }; F53F21F2022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesGroupedIconView.m; path = src/preferences/MVPreferencesGroupedIconView.m; refType = 2; }; F53F21F3022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesMultipleIconView.h; path = src/preferences/MVPreferencesMultipleIconView.h; refType = 2; }; F53F21F4022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesMultipleIconView.m; path = src/preferences/MVPreferencesMultipleIconView.m; @@ -3548,11 +3881,13 @@ refType = 4; }; F53F21FF022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; path = PersonalPane.h; refType = 4; }; F53F2200022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; path = PersonalPane.m; refType = 4; @@ -3666,12 +4001,14 @@ }; }; F541495A02711A8301A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHToolbarAdditions.h; path = src/extensions/ToolbarAdditions.h; refType = 2; }; F541495B02711A8301A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHToolbarAdditions.m; path = src/extensions/ToolbarAdditions.m; @@ -3690,12 +4027,14 @@ }; }; F541495E02711B0001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHImageAdditions.h; path = src/extensions/ImageAdditions.h; refType = 2; }; F541495F02711B0001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHImageAdditions.m; path = src/extensions/ImageAdditions.m; @@ -3744,12 +4083,14 @@ }; }; F549ACDE0302DE6001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolTip.mm; path = src/browser/ToolTip.mm; refType = 2; }; F549ACDF0302DE6001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = "NSScreen+Utils.m"; path = "src/extensions/NSScreen+Utils.m"; @@ -3780,6 +4121,7 @@ }; }; F549ACE40302DEBB01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = "NSScreen+Utils.h"; path = "src/extensions/NSScreen+Utils.h"; @@ -3798,6 +4140,7 @@ }; }; F549ACE70302DEF001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolTip.h; path = src/browser/ToolTip.h; @@ -4064,12 +4407,14 @@ }; }; F558099D02F22168015DF512 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSString+Utils.h"; path = "src/extensions/NSString+Utils.h"; refType = 2; }; F558099E02F22168015DF512 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSString+Utils.mm"; path = "src/extensions/NSString+Utils.mm"; @@ -4094,12 +4439,14 @@ }; }; F5581379030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = RemoteDataProvider.h; path = src/browser/RemoteDataProvider.h; refType = 2; }; F558137A030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = SiteIconProvider.h; path = src/browser/SiteIconProvider.h; @@ -4116,12 +4463,14 @@ refType = 4; }; F558137C030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = RemoteDataProvider.mm; path = src/browser/RemoteDataProvider.mm; refType = 2; }; F558137D030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = SiteIconProvider.mm; path = src/browser/SiteIconProvider.mm; @@ -4176,12 +4525,14 @@ }; }; F558B1F0030F6E470166970F = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserListener.h; path = src/embedding/CHBrowserListener.h; refType = 2; }; F558B1F1030F6E470166970F = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserListener.mm; path = src/embedding/CHBrowserListener.mm; @@ -4305,6 +4656,7 @@ }; }; F55C4DD302D2864D0130B065 = { + fileEncoding = 30; isa = PBXFileReference; name = UserDefaults.h; path = src/application/UserDefaults.h; @@ -4329,12 +4681,14 @@ }; }; F55EBC9A0383665201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksExport.h; path = src/bookmarks/BookmarksExport.h; refType = 2; }; F55EBC9B0383665201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksExport.mm; path = src/bookmarks/BookmarksExport.mm; @@ -4365,6 +4719,7 @@ }; }; F5607CB5023944AD01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = GeckoUtils.h; path = src/extensions/GeckoUtils.h; @@ -4434,12 +4789,14 @@ }; }; F5648739023C3857010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = IconTabViewItem.h; path = src/extensions/IconTabViewItem.h; refType = 2; }; F564873A023C3857010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = IconTabViewItem.mm; path = src/extensions/IconTabViewItem.mm; @@ -4464,6 +4821,7 @@ }; }; F56610A1039474CB01A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraVersion.r; path = resources/application/ChimeraVersion.r; @@ -4498,6 +4856,7 @@ F56610A40394767101A9666E = { children = ( F56610BC0394775201A9666E, + A7F01A4803CBBCA500A967F8, ); isa = PBXGroup; name = Plugins; @@ -4544,12 +4903,14 @@ }; }; F566BD1202EFA9AD01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = CocoaPromptService.h; path = src/browser/CocoaPromptService.h; refType = 2; }; F566BD1302EFA9AD01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = CocoaPromptService.mm; path = src/browser/CocoaPromptService.mm; @@ -4580,6 +4941,7 @@ }; }; F56769FB0208F74A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindowController.mm; path = src/browser/BrowserWindowController.mm; @@ -4598,12 +4960,14 @@ refType = 2; }; F568C3CF023A4A5A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = AboutBox.h; path = src/application/AboutBox.h; refType = 2; }; F568C3D0023A4A5A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = AboutBox.m; path = src/application/AboutBox.m; @@ -4646,6 +5010,7 @@ }; }; F56F241F02AC6D0401A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = nsStaticComponents.cpp; path = src/application/nsStaticComponents.cpp; @@ -5250,6 +5615,7 @@ target = F5A8CE4702DFF039013CA8EC; }; F56F837202E47CCD01EF35C9 = { + fileEncoding = 30; isa = PBXFileReference; name = RegionNames.strings; path = PreferencePanes/Appearance/English.lproj/RegionNames.strings; @@ -5271,12 +5637,14 @@ }; }; F57074B5026BA85F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksToolbar.h; path = src/bookmarks/BookmarksToolbar.h; refType = 2; }; F57074B6026BA85F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksToolbar.mm; path = src/bookmarks/BookmarksToolbar.mm; @@ -5295,12 +5663,14 @@ }; }; F57074B9026BFD0101A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksButton.h; path = src/bookmarks/BookmarksButton.h; refType = 2; }; F57074BA026BFD0101A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksButton.mm; path = src/bookmarks/BookmarksButton.mm; @@ -5319,12 +5689,14 @@ }; }; F57074BD026D80DF01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = LocationBar.h; path = src/browser/LocationBar.h; refType = 2; }; F57074BE026D80DF01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = LocationBar.mm; path = src/browser/LocationBar.mm; @@ -5354,6 +5726,7 @@ refType = 4; }; F57BED9703A1824001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = NetworkServices.mm; path = src/rendezvous/NetworkServices.mm; @@ -5372,6 +5745,7 @@ }; }; F57BED9A03A1824801A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = NetworkServices.h; path = src/rendezvous/NetworkServices.h; @@ -5390,12 +5764,14 @@ }; }; F57BED9D03A1825001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = DNSUtils.c; path = src/rendezvous/DNSUtils.c; refType = 2; }; F57BED9E03A1825001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = DNSUtils.h; path = src/rendezvous/DNSUtils.h; @@ -5506,7 +5882,6 @@ "; - shouldUseHeadermap = 0; }; F57F205D029997E701000106 = { children = ( @@ -5534,12 +5909,14 @@ refType = 2; }; F57F2060029997E701000106 = { + fileEncoding = 30; isa = PBXFileReference; name = PrivacyPane.h; path = PreferencePanes/Privacy/PrivacyPane.h; refType = 2; }; F57F2061029997E701000106 = { + fileEncoding = 30; isa = PBXFileReference; name = PrivacyPane.mm; path = PreferencePanes/Privacy/PrivacyPane.mm; @@ -5700,12 +6077,14 @@ refType = 4; }; F5807369023A1514010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = SplashScreenWindow.h; path = src/application/SplashScreenWindow.h; refType = 2; }; F580736A023A1514010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = SplashScreenWindow.mm; path = src/application/SplashScreenWindow.mm; @@ -5850,7 +6229,6 @@ "; - shouldUseHeadermap = 0; }; F58581AF022B8D62010001CA = { buildActionMask = 2147483647; @@ -5941,19 +6319,22 @@ F507A84A03116E6E01026D5D, F507A84D03116E7401026D5D, F507A85003116E7901026D5D, - F5C8D55203A2A42401A8016F, + A7AEBED703CB9C2F00A967F8, + A7AEBED903CB9C2F00A967F8, ); isa = PBXGroup; name = Nibs; refType = 4; }; F58DB2D20381FD3301A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = JSConsole.h; path = src/application/JSConsole.h; refType = 2; }; F58DB2D30381FD3301A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = JSConsole.mm; path = src/application/JSConsole.mm; @@ -5984,12 +6365,14 @@ }; }; F59236C002C89AC90100012B = { + fileEncoding = 30; isa = PBXFileReference; name = AppDirServiceProvider.cpp; path = src/application/AppDirServiceProvider.cpp; refType = 2; }; F59236C102C89AC90100012B = { + fileEncoding = 30; isa = PBXFileReference; name = AppDirServiceProvider.h; path = src/application/AppDirServiceProvider.h; @@ -6039,6 +6422,7 @@ refType = 2; }; F5949A47030D58A1014E8430 = { + fileEncoding = 30; isa = PBXFileReference; path = xhtml11.dtd; refType = 4; @@ -6106,6 +6490,7 @@ }; }; F59E9F3D0237E28401A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = ContentClickListener.h; path = src/browser/ContentClickListener.h; @@ -6118,6 +6503,7 @@ }; }; F59E9F3F0237E43401A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = ContentClickListener.mm; path = src/browser/ContentClickListener.mm; @@ -6154,6 +6540,7 @@ }; }; F5A3669302CCFAF601DC3354 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksDataSource.h; path = src/bookmarks/BookmarksDataSource.h; @@ -6176,6 +6563,7 @@ refType = 4; }; F5A3669502CCFAF601DC3354 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksDataSource.mm; path = src/bookmarks/BookmarksDataSource.mm; @@ -6542,12 +6930,14 @@ refType = 4; }; F5A8CE4102DFEF4C013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = PreferencePaneBase.h; path = PreferencePanes/Shared/PreferencePaneBase.h; refType = 2; }; F5A8CE4202DFEF4C013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = PreferencePaneBase.mm; path = PreferencePanes/Shared/PreferencePaneBase.mm; @@ -6632,7 +7022,6 @@ "; - shouldUseHeadermap = 0; }; F5A8CE4802DFF039013CA8EC = { buildActionMask = 2147483647; @@ -6698,12 +7087,14 @@ refType = 2; }; F5A8CE4E02DFF167013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = Appearance.h; path = PreferencePanes/Appearance/Appearance.h; refType = 2; }; F5A8CE4F02DFF167013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = Appearance.mm; path = PreferencePanes/Appearance/Appearance.mm; @@ -6782,6 +7173,7 @@ }; }; F5AE04B20206A34801A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindowController.h; path = src/browser/BrowserWindowController.h; @@ -6794,6 +7186,7 @@ }; }; F5AE04B60206A37C01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = MainController.h; path = src/application/MainController.h; @@ -6806,6 +7199,7 @@ }; }; F5AE04BA0206A4FE01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = MainController.mm; path = src/application/MainController.mm; @@ -6818,12 +7212,14 @@ }; }; F5B34B01034A505F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSPasteboard+Utils.mm"; path = "src/extensions/NSPasteboard+Utils.mm"; refType = 2; }; F5B34B04034A50C901A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSPasteboard+Utils.h"; path = "src/extensions/NSPasteboard+Utils.h"; @@ -6876,10 +7272,12 @@ F5FDF166031AF47301DE816D, F5D98EBC031AC38601A96654, F558099D02F22168015DF512, + A7AEBEC403CB962500A967F8, F549ACE40302DEBB01026D5D, F5B34B04034A50C901A80166, F5648739023C3857010001CA, F5C3AB810270072A01A80166, + A7AEBEDF03CB9CD700A967F8, F541495A02711A8301A80166, F541495E02711B0001A80166, ); @@ -6892,9 +7290,11 @@ F5D98EB9031AC37801A96654, F558099E02F22168015DF512, F549ACDF0302DE6001026D5D, + A7AEBEC703CB964000A967F8, F5B34B01034A505F01A80166, F564873A023C3857010001CA, F5C3AB820270072A01A80166, + A7AEBEE203CB9CEC00A967F8, F541495B02711A8301A80166, F541495F02711B0001A80166, F5FDF167031AF47301DE816D, @@ -6905,12 +7305,14 @@ refType = 4; }; F5B950BC030C83B601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabViewItem.h; path = src/browser/BrowserTabViewItem.h; refType = 2; }; F5B950BD030C83B601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabViewItem.mm; path = src/browser/BrowserTabViewItem.mm; @@ -7184,7 +7586,6 @@ "; - shouldUseHeadermap = 0; }; F5BAAB1A02AC45D301A967F3 = { buildActionMask = 2147483647; @@ -7229,7 +7630,6 @@ F50D9DE702ECC36201BB4219, F50D9DE802ECC36201BB4219, F5E37B0C02EE959601A967F3, - F5E37B0D02EE95E201A967F3, F5E37B0E02EE95E201A967F3, F5E37B0F02EE95E201A967F3, F5D33CC202EF61AA01A967F3, @@ -7254,6 +7654,9 @@ F57BEDA203A1825001A9666E, F5C8D55403A2A42401A8016F, F5C8D55703A2A43301A8016F, + A7AEBEC503CB962500A967F8, + A7AEBEE103CB9CD700A967F8, + A7AEBEEA03CB9DFB00A967F8, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -7343,6 +7746,12 @@ F5566DC9038E075F01A80166, F5566DCA038E075F01A80166, F5566DCB038E075F01A80166, + A7AEBED403CB9BD000A967F8, + A7AEBED503CB9BD000A967F8, + A7AEBED603CB9BD000A967F8, + A7AEBEDD03CB9C2F00A967F8, + A7AEBEDE03CB9C2F00A967F8, + A7F01A4A03CBBCA500A967F8, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -7389,7 +7798,6 @@ F5A3669B02CCFB7A01DC3354, F5A3669C02CCFB7A01DC3354, F50D9DE902ECC36201BB4219, - F5E37B1002EE95E201A967F3, F5E37B1102EE95E201A967F3, F5E37B1202EE95E201A967F3, F5D33CC302EF61AA01A967F3, @@ -7413,6 +7821,9 @@ F55EBC9F0383665201A80166, F57BED9903A1824001A9666E, F57BEDA103A1825001A9666E, + A7AEBEC803CB964000A967F8, + A7AEBEE403CB9CEC00A967F8, + A7AEBEE703CB9DDF00A967F8, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -8253,6 +8664,8 @@ F5BAAC0402AC693C01A967F3, F5BAAC0502AC693C01A967F3, F5BAAC0702AC693C01A967F3, + A7AEBEB403CB955700A967F8, + A7AEBECB03CB96E700A967F8, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -8994,12 +9407,14 @@ }; }; F5BF71450231B8BC010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabView.h; path = src/browser/BrowserTabView.h; refType = 2; }; F5BF71460231B8BC010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabView.mm; path = src/browser/BrowserTabView.mm; @@ -9048,12 +9463,14 @@ }; }; F5C3AB810270072A01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = ExtendedOutlineView.h; path = src/extensions/ExtendedOutlineView.h; refType = 2; }; F5C3AB820270072A01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = ExtendedOutlineView.mm; path = src/extensions/ExtendedOutlineView.mm; @@ -9072,6 +9489,7 @@ }; }; F5C8D55203A2A42401A8016F = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraUIConstants.h; path = src/includes/ChimeraUIConstants.h; @@ -9090,6 +9508,7 @@ }; }; F5C8D55503A2A43301A8016F = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraUIConstants.h; path = src/includes/ChimeraUIConstants.h; @@ -9152,6 +9571,7 @@ refType = 4; }; F5D1421902BC88F801A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = "redo-prebinding.sh"; path = "src/scripts/redo-prebinding.sh"; @@ -9164,18 +9584,21 @@ }; }; F5D33CBC02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityDialogs.h; path = src/browser/SecurityDialogs.h; refType = 2; }; F5D33CBD02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = AppComponents.mm; path = src/application/AppComponents.mm; refType = 2; }; F5D33CBE02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityDialogs.mm; path = src/browser/SecurityDialogs.mm; @@ -9230,6 +9653,7 @@ }; }; F5D98EB9031AC37801A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSBezierPath+Utils.mm"; path = "src/extensions/NSBezierPath+Utils.mm"; @@ -9248,6 +9672,7 @@ }; }; F5D98EBC031AC38601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSBezierPath+Utils.h"; path = "src/extensions/NSBezierPath+Utils.h"; @@ -9266,6 +9691,7 @@ }; }; F5DA444A027DD5AA01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "installed-chrome.txt"; path = "../dist/Embed/chrome/installed-chrome.txt"; @@ -9326,36 +9752,42 @@ }; }; F5DE10E60209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = nsAlertController.h; path = src/browser/nsAlertController.h; refType = 2; }; F5DE10E70209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserView.h; path = src/embedding/CHBrowserView.h; refType = 2; }; F5DE10E80209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserService.h; path = src/embedding/CHBrowserService.h; refType = 2; }; F5DE10E90209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = nsAlertController.mm; path = src/browser/nsAlertController.mm; refType = 2; }; F5DE10EA0209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserView.mm; path = src/embedding/CHBrowserView.mm; refType = 2; }; F5DE10EB0209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserService.mm; path = src/embedding/CHBrowserService.mm; @@ -9403,12 +9835,6 @@ settings = { }; }; - F5E37B0D02EE95E201A967F3 = { - fileRef = F50D9DF102EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F5E37B0E02EE95E201A967F3 = { fileRef = F50D9DED02EE0AB101BB4219; isa = PBXBuildFile; @@ -9421,12 +9847,6 @@ settings = { }; }; - F5E37B1002EE95E201A967F3 = { - fileRef = F50D9DF202EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F5E37B1102EE95E201A967F3 = { fileRef = F50D9DEE02EE0AB101BB4219; isa = PBXBuildFile; @@ -9506,6 +9926,7 @@ refType = 2; }; F5F190BB02D1F81A01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolbarDefaults.plist; path = resources/application/ToolbarDefaults.plist; @@ -9524,6 +9945,7 @@ }; }; F5F190BE02D217C201026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebsiteDefaults.strings; path = resources/application/WebsiteDefaults.strings; @@ -9569,12 +9991,14 @@ }; }; F5F94B900332532801026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = KeychainService.h; path = src/browser/KeychainService.h; refType = 4; }; F5F94B910332532801026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = KeychainService.mm; path = src/browser/KeychainService.mm; @@ -9633,6 +10057,7 @@ }; }; F5F9FBD902E13767012B5DB7 = { + fileEncoding = 30; isa = PBXFileReference; name = RegionMapping.plist; path = PreferencePanes/Appearance/RegionMapping.plist; @@ -9669,6 +10094,7 @@ }; }; F5FCDD5D03A035E001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = Localizable.strings; path = English.lproj/Localizable.strings; @@ -9689,12 +10115,14 @@ }; }; F5FDF166031AF47301DE816D = { + fileEncoding = 30; isa = PBXFileReference; name = DraggableImageAndTextCell.h; path = src/extensions/DraggableImageAndTextCell.h; refType = 4; }; F5FDF167031AF47301DE816D = { + fileEncoding = 30; isa = PBXFileReference; name = DraggableImageAndTextCell.mm; path = src/extensions/DraggableImageAndTextCell.mm; @@ -9747,12 +10175,14 @@ //F63 //F64 F632AF8302B9AEBB01000103 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindow.h; path = src/browser/BrowserWindow.h; refType = 2; }; F632AF8402B9AEBB01000103 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindow.mm; path = src/browser/BrowserWindow.mm; @@ -9771,6 +10201,7 @@ }; }; F6BA6D4E01B2F8A601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWrapper.mm; path = src/browser/BrowserWrapper.mm; @@ -9946,6 +10377,8 @@ F517941F027F3F2901A967DF, F53A902202C1127A01A967F3, 98590B3603A8938A45A2FA2A, + A7AEBEB103CB950400A967F8, + A7AEBECA03CB96D600A967F8, ); isa = PBXGroup; name = "Gecko Components"; @@ -10079,6 +10512,8 @@ F6BD64B601B3167601A962F7, F53A902402C1137901A967F3, 98E1988603A8A6F345B32312, + A7AEBEB303CB954500A967F8, + A7AEBECC03CB96F900A967F8, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -11091,30 +11526,35 @@ runOnlyForDeploymentPostprocessing = 0; }; F6BD64B801B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = charsetalias.properties; path = ../dist/Embed/res/charsetalias.properties; refType = 2; }; F6BD64B901B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = charsetData.properties; path = ../dist/Embed/res/charsetData.properties; refType = 2; }; F6BD64BA01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = langGroups.properties; path = ../dist/Embed/res/langGroups.properties; refType = 2; }; F6BD64BB01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = language.properties; path = ../dist/Embed/res/language.properties; refType = 2; }; F6BD64BC01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = maccharset.properties; path = ../dist/Embed/res/maccharset.properties; @@ -11167,12 +11607,14 @@ refType = 2; }; F6BD64D301B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = htmlBindings.xml; path = ../dist/Embed/res/builtin/htmlBindings.xml; refType = 2; }; F6BD64D501B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = platformHTMLBindings.xml; path = ../dist/Embed/res/builtin/platformHTMLBindings.xml; @@ -11192,30 +11634,35 @@ refType = 2; }; F6BD64D801B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Latin1.properties; path = ../dist/Embed/res/entityTables/html40Latin1.properties; refType = 2; }; F6BD64D901B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Special.properties; path = ../dist/Embed/res/entityTables/html40Special.properties; refType = 2; }; F6BD64DA01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Symbols.properties; path = ../dist/Embed/res/entityTables/html40Symbols.properties; refType = 2; }; F6BD64DB01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = htmlEntityVersions.properties; path = ../dist/Embed/res/entityTables/htmlEntityVersions.properties; refType = 2; }; F6BD64DC01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = transliterate.properties; path = ../dist/Embed/res/entityTables/transliterate.properties; diff --git a/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib b/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib index 7734e3e1f0e..d089e644067 100644 --- a/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib +++ b/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 646 106 458 263 0 0 1600 1002 + 674 107 458 263 0 0 1600 1002 IBEditorPositions 214 @@ -12,6 +12,6 @@ IBFramework Version 286.0 IBSystem Version - 6D52 + 6G30 diff --git a/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib b/camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib index d46732370de770898b359b688a589650ae3aae8c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 14811 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 diff --git a/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib b/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib index 7398ee93826..53d0766d0b8 100644 --- a/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib +++ b/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib @@ -17,11 +17,7 @@ IBLastGroupID 8 - IBOpenObjects - - 5 - IBSystem Version - 6F21 + 6G30 diff --git a/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib b/camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib index 88d9df4efe6447297553e3dc3b792a02a09fc079..2d20a0a29720f2bb991aa90b7ae4c7c9a0b4b41d 100644 GIT binary patch literal 10394 zcmbVSeRLF6mVYl_d<8;)fKdiI%a;L-LSzpM$|NC^0g(U(aX5nqI-N?=rqdO>JA{m$ zJ-keH|1)#;?CBwOhzoHBzYv1JM#foZ84;9`^;BRGT)&WyRY@c$sEC55_jg}abyq@& z%yd#!uim@wzWeUI@4kEQtCV4(#yX`U7z!xvT9MqT@d8cLMwFHW5p@7$4#W!kv#+0RjswL{Lygr|MLAAG5 z3AmR9lu9L__&rLgd!4t+9rCLFNI0T#?|nMDr_H`1r}`_D0NY4I zrk0i!sq3dd8P%SQhFh4HUVvYv^)pFYQXg`c`;@{!z}?6+ZBS{MS=`t%h%kV-qWVxs z^`mV_Y1snR9}1|x+$W>0ElooiV_U-bjT$bJQb#dH_h@T0On+L6*W)Q*9R0L(8_5F2 z=liLAFZ9qf=silG?ubf}RM8#T#`-`u%#Nrg>`JkMAXhYkXGR7z4)@$C@h z?^}|h+H=n}X{1TSol#4nKS8j@uQXUnl$ig%og`IeN>$UqYHLkctC9qLAgsMe5*>~u z=C1In=9(a}%7LWH(m)x`fuN#t6i!;?9Ob})@as^By~M(oIFD>6V&gbc

G-!aD{3 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 literal 10392 zcmbtadvp|4n!mU6fCOSlFuX*mEI~jN1x_SrAB_lw^k1O)Ic;6)wu629o3t1ir@b;O&bk_ zUSfgD1ty7@3l; zR?hoN@2YGtHVMzgIJ<|nGB5M7dM2}9vLN08mD7AL_l^K^c#si zt7Ul0%ZY2qtV;E(kaKsomSM4xUE3ZCE6q`GG}>$F$ApP$FLq~Wo`#0s{QRcw7kQM* z**#kUHpT`coJEN6n{7fpU&-O9RqLCMQRhiS!?t>Lg5U{8>dzvI@YL=UnkTn;) zYI92~Ok8@T)gOSnz~rT&>SZuX{aS+R+MwJVnjPKZ2yB;2b)7NowUk*c*lU9QMleGH z=Xj@Z{s-HfM&8LxMNM2vs!2P=66)#OMoQruq8rNN&<1>h?PF}OM|#qB;}wB9PR3lE zd#5!QueIjlLd-iqdj#(=W~7(N31dVTOa^$O++yLGDcF~w*i0=?6pKV%hPY0!KEXT3 zkv==erEo?1tgsyqnP1M|+*+-ww^qu*q>*)Q<&L>`k=xCKYm@89yDq}KW*fB;ru~(d zN4f}uV-KNdH++QYmTmCNC&~M2`)nWFrTxB>#|{t|JV$u$75o%DY@Ofg|zrP;Y4>~e1C{b_##*He=?VHXUvNeB+K>(de>{#H@ zgFoFjWJek2By^kHen&N6rqpJtGW2bU4SzMCW12J#$u#|Eul zrsuGY&@{kNHAx>Fbj; zz~S zvqwrH=l|kx&$%4#PRq0Y*_;8ImW8EIU3b%yrWu)@2h;C@J>@(e;mPJ80`J%bdz#W5 z9<@k#azgEOEQ#bvY4|1_J;*vh~7 zGOgilxeCL}t5xKnxA79w%Sx)jaZxF&N56~r+!4Zam*A6$drD*bt;RPXy-aed5HOz; z9VDlpuygXE{ie&^X}erNk0AG!=UR~p^Mogh3?1)S-enxzEvBa+w}3Fhc65>&H2snj z?banGa&mg*r?-Fi_yvL;5PZ8Czi%%{pvV>@)36z8zP5*V|Z#PLZ zs?_FYIZ!`SYEs(GK+Wa93X{UNZV+s<;OB0HIPi886VVE%`tU0& zE2Eu?73Xbc%)@D!;O7c6JsTFxfEk(#A0~{3O@!%q3Mo1Xf#g79kw^-t$P^H>Vnqr+ zCPlPAQBa7LeYsrkQ>~bhBEy*GUUKr?Sg|~qC^>Bb+$bkaid=_D*L`w(O6M#Sb&`t6 zHo^aXF{rrn-gsmubusN=f;n$el=Z0KkD97_^hZ=h24iW;Tvme0!>tPT9`#aPyCes! z5Y!cQx>Qx{R@Jyv_53v?U1ln$EJZp03{7NQs)-C!W>=?)lHr<|Vag#zZqtVe-7)=! zAU0FYYA9^ajifT%SZAccIBB`k8iLcNMOazq3x!E$)&w(=cu1o_VyOokik&+V$6;@0 z?jmMyj76{=vNlDOT6x+cnSZ^7g&Gf`NH#wPUe_0HmRroO%as=Fdvk3>RNB}nvIevf zE9cz)SGRdrEm^{DVk~Qd8J=DKm4PPrb9u;1Td3dsf`WqIPMYmAyC;v7lCuhEm`_i7tnyjLtqSj^0mJMy$vL*iEhabkzojVslfBt;@gAYE4cXxNk zSFBhuG-b+^R&>GIk@lB0apJ`G*4EauZ@&3v{D&WYh^PC#`|i8(#~yp^?6hgq+SB05 z03X#4J@nAA?c2A#euqZEbDGFm5$)ksO>~Ze?ZV zGcUdLQhfLB-SIEJ_#*zzH{Zm+{q|e)Ieq%HnNr=CUw#=M7#N86_V&i_zWeTHfPi+p z&Tss>b?XlA+O;dbZ{NQ7;lqdHpMU;&{Hw3NGM`hYPMI_kokxxwiTC&S$KQVYZQ}1R z5RA8x5M3qDJ@?#q)PCsDq4?0ykO}|kr=P};9Xl5P?6c3}lqVd6gM+5b_wU~y-@0|{ zchnb;V;i$ye);9|2M-=J;Xe7~llbxD$4&lDoH&ul6FzFAacI14+qRttj@fQJPd)Y2 z32LWti6@c+@k7toUw>_;R7Y(@vQMk_*Z7%$YN$?T`(T zo~TSXNe@I()KxzyJPwQ*T5g!QOoH&A+3* zguwoh?y6R=UOj+uE;=~U*&*2{__|22)CZ4S?<8-+tJKxieFXcskPZjcz4zXG7wYTl zKO$JW5A}8bXueFrqs*H(uW$YO^`~G@KakDPLwTyBHiEHXFFVK3PIM8yZFru>v(0`e zPj%ErFqgxDCi6#h63+xnx*+?Yhw@ZMZNqs%)fImP?|v>1oQK$yAUQ+O#JMZ)G4q*V z;0>N(*8`Ym+j$T21q|)z%h*U>WY?pHk9X>`#_&m|1OSuO$FED|{|(WfH7?`Cwwn;h3_OH;mPB%QY)N{ zQhYmFu$b@^K)LjGR_{MvE^xoY3EVFosw~}5W$vM7{Dgt#TLYyH!D;cuUlj3JKF%=e z5WZ9fvB$?EoeZv>^9)D=X9thRDs1ww3*R7^8Q9_-tFUmTJr6|`(5y7q(eartTHyQ zIPv#|nr53@Iz;wFBb{$`upos^mJxlIsFcDpe7?$#}o^DuoJRUA0&{79x68gY8n#w&jqNlpXF% zq(=D>B_UP_lS1AE;}VpDvlK__mc(U9PxgmY2_Z7hsZ=S{x)#O}mhM}A55#UBJxg>C zM!1?C`QM{j2ia1c9CQivLAO9J!ceUvcE^9MOga_*PvpPwj;(Y#l~wl({yKRtyd4X> ztoK^wc(0^|7TmuSlWXafCs%GdZLPU7g?W> zZS^AWjw=|au-iU>9*A%)lQ2N#SxjVn-pzXjdrvSyd#-4QetnUCZcv|4r03`9^UL&^ zC3T4?WGlTl+ zLH+okzN|v8DA(Bqy(mvF%+q&t={f!St}eZ{Lhs+NS5@dGd3tf4UY4gH7|=`ebj7PL zuFw}&==%@q4_4?ygZk)xeZb#&t9}&BU{hzE8r(i7s&`sv35myWD#>hAKVwxTNr>vFQI#^laa5$T zx9rkh3{{DNickO*))^LPE*u6Asu!cmrIZ{LQ*Vo+`mSNUfT$K#Kx}b_8zw!|hRh;jj*bf6eeZ5Y~aZ(bc%R zoF0;vw&4~sst={2qGJ%~$GQ1a!ni2MVRS7r`08O1B4aEEvk2uU%}Nw zAb>9_)SzJd%x^5vlBg@#*yAUgDDnk-VV~@;_60-X#77Qvor@#Io}A-?{iB^Phd*}m zr)esT3cx-WEA6I1*+A!p1bflW4;{7gnpR{|g|X?&iUbKDOR(pAP80vdSm(V>b?Q3Y zOjwuwbR0}Em3elm)R$Q#_4b@2@CkIJYr#27@iIA}_!Cgo1a&PgeQ9Z5fXHu&TJLM{ zx$rC|h_POZ;eP2?>tw&Z2qaJp5x_);uG+9145y>#=+%I2?&%?D3}$O808POJNtcK!frtFgwPDA5*o=`B5)d?X3z87Ftes{*@iekt@hkXX zMsaF8$U%-+-Da*?iApk}ywwe4J}I`)+fz$e@=Xa-cwokIwsbf5)SA9AjRkd(qcd;V z%#U)cO9&FYGhzk_A)W1Y5L5Z9ZG%oBW^>QzA~asv*o(+Rq(fYiFWCFGQCBZc<`>r{ z^LzUQJ7~l7?MT)i&q(Gw$VE?f^h+nrP;h8bAbFK&@z~qbN22>tBi}(#V;p?LCrZ&3 zTT8Ckntz2>*fK57`OVHPeYN@VkfWXsa)SlUzo0KKl!fM(8Wk-qNy{T4UlXJ&0y>ng zR)ZD4NOUbi+xSEq2?y==^@#c5PNz@vl>4%9^JsDJ{YIYPxyFSDjZ(qKq47`ncEqTfVyqN=l5uJg zYPJaWv~ftVGsxq!l2?%I5$sK44Q|qq-zC`VNV@R>jZrLkmN8%OiKsXv_*5jH2|gPM zwoJW9@W00>5qyL(Q}9tJy(f4vk~an0iR7^0Gmv~N_$(yb1$)`pCHPolXf%pFpxl@s zIOYFS@V_wL7wmtGiW^XT1+B&`!84KH3TYwv6dzw8d0Vi5G4ch^Hi`rviHZY)y=x%G zy}|Hj8JHFOje~-nHga+dd|6Ut?7&VQP&)IC8>Q&`xeA%P4sX;j4{{_@dVwC^@ diff --git a/camino/resources/images/app/disclosureArrowDown.tiff b/camino/resources/images/app/disclosureArrowDown.tiff new file mode 100644 index 0000000000000000000000000000000000000000..fc9d9ee2497c56779ddb98df7fcbe23fa43466a3 GIT binary patch literal 1422 zcmd6n&r9227{|YF+G!~)b8DU89AqM{6?D>LZ_&yaDA+1vdNV%|bZOEg+w`Qj?GM;- z#~nTB(Sxv?7YDM!&SMw+LeESF6>PWQONA`MH)(ryo$J8ReQh@08(sxm=#2%qfqz@v}#k@>Hj+jW!2tJlfzU?*sfa<8kkj(4m{|*0$}s!p8n26j zUQ|ls<0VBkY|T{W);-^}JmpPYA4B*)>_S#`ocE?eClpNY_Q7W!cKlZj&Qd%*h_!ev r{e$~4nhEg}=roUetkXY>TBGl7H`d;s0$Z-V$tT8*xuC1Qho1S~_ zu}49BEVSUIH-%!MXHWhE7U{u)Z}vwwiZ;f&VRt_Bo%elj=Iv&B8bg4#ga5cnrP6G( zb|J(!*LA;`ra63DuaxqSx;@W3=A6IJ<#PE(-q;h5b)j5*lVPpRjbwACOo&U)699A>Dyi2&t1NQt3CPWJj;L-MKEOO!RlBGSf}Mh zmWp%=W-SqG#2uh@@&awFE7D0}4`W^X$R0s`6{?KQdj9e&)?1g;tjk$R^eqpq^iS#~ zucRDQCHke$-vNW|h)0UCO5+n+JFr&sWo2^Qm|s{lT90TSX|&)83NN`QteKhTDoxF; zIcmIoo&5|>f*->w*X6Z_vosgdr>Jwf`isfA88R>h( z+2xS;726?yS1joe6mv|RUk>?~Vmn~1O|kE6sJbxuQ=>38Rxqq3*LIBAP0x4MJY%ZH zM-c8uMImhoQFRRJP%ypUhw6El@w6QDl64;>T2hOz%h%D2u|uHIJjt>76|gFR{yEWJ U{04SLfyb#t8|VW%-vXb+1wYEd?*IS* literal 0 HcmV?d00001 diff --git a/camino/resources/images/app/small_close.tiff b/camino/resources/images/app/small_close.tiff new file mode 100644 index 00000000000..e69de29bb2d diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib index 8d9ef756813..8cb98c23986 100644 --- a/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib +++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/classes.nib @@ -68,6 +68,7 @@ closeCurrentTab = id; closeOtherTabs = id; closeSendersTab = id; + copyImage = id; copyImageLocation = id; copyLinkLocation = id; endAddBookmarkSheet = id; @@ -80,6 +81,7 @@ goToLocationFromToolbarURLField = id; home = id; manageBookmarks = id; + manageHistory = id; moveTabToNewWindow = id; newTab = id; nextTab = id; diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib index ae6ff6280c5..2647aded841 100644 --- a/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib +++ b/camino/resources/localized/English.lproj/BrowserWindow.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 66 21 653 383 0 0 1152 848 + 65 36 653 383 0 0 1152 848 IBEditorPositions 124 @@ -15,17 +15,17 @@ 297 107 466 213 294 0 0 1600 1002 314 - 73 542 213 132 0 0 1600 1002 + 72 544 213 150 0 0 1600 1002 336 486 756 213 180 0 0 1600 1002 365 31 719 93 162 0 0 1600 1002 463 - 97 693 213 246 0 0 1600 1002 + 349 487 213 246 0 0 1600 1002 56 450 634 343 68 0 0 1280 1002 654 - 206 785 198 144 0 0 1600 1002 + 140 644 198 144 0 0 1152 848 IBFramework Version 286.0 @@ -42,6 +42,6 @@ IBLockedObjects IBSystem Version - 6F21 + 6G30 diff --git a/camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib b/camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib index 6ea50d4bb91c16ff7f6c317617a9ec2de61c1312..3a5bafda9055e11d58cd6d1028a66304b2c83f0e 100644 GIT binary patch literal 19032 zcmbVU3w%`7nLp>|{U9$w1f)2M^??*NsMV%b5`u*MfPfClu5Hy}auY^o=Ej+c0qZWF zVP@8~t8J&rloS?9Q>_akrK}HH7g(wIs4J`Zt`&b!mpUu!?yud}$FF4n-#Pc*xigcO zsF`!`cfRwT?|kQboyWDXBC?@J?+iymx+fqCejnq_u~@9C!`;4c#hTl7Z)A}t;t}k< zSgf?etspF(R4A>z;fN7Xz)SmMS~E2TnmZEm1-p5Fj9+%n!jRDy)j}-u8$d5d4#VqF$^(g1y)uEA%xtH?!F0&4q-OP<=1& zjd<4h^_Eb`vw_88B^_?{*gsg3jQudVB{m7I+S{pVbCXXtFX_wFpGm^O@~_z=LS7&^oG3prTr=3fo^-i)2&mRYQ^@6Rs;_xQKBj z!Nk}tqlXw{Lu2C*FJ-NMBP_{}PH-^8dW}L~5m~E;h^O$VtrA0t?PD{sg=TzGhkK>b zb7RlK-blm1!IsNhE{=sM^B=b-_PIFy}=~C+B)+6Yy2r7#Q=xaMqLON4A+>3pF zJ?IJO;gxF)PpEShY$TDW672g+n;2W#l-y5~n~Xy@z20WVLB#H|RrmW9+w{}|yYTs< zjGtjFR!FRxI#Uac?dkFRyq<{92)28TAe08|75IEUunP0=a%j(E#QXUs?{UFzt6b$` zY?aI6V3+C~LsHVCJ{QO#ws?s!z1JRoG+GD-qNP_ewg&^$RxBkmf{`tTn5Xm)UKlI- z`sH8tezO=IO~>DvVYZC*GB5M7PUc~4EQH@6o^_0ZcTL*M_Hz6cf@2J?N$UEMSXnsi zlLpr;*mKi(G!bnc9zu6~5-jD#!5Qde{?)3JdezAi5cIP<@f$%`Ugmk+BF*3-Mi_qO zNW*_FXL!Y}o}gFvCw?7|KOtE=`eY76=O*GWN&0fyR_W^_i+#Gkb6S?B#ESx}8yH*N zkRxmO0lNi>_uA*p{tKIxc#AurIZfr6{*T29yyU{9pK3My2Gn@DGEU)JJGGM)aE{B~b3a<4jAG zkw}K@i8%Qbw+Asf0`3=jyz9C{MsKjwF%Iq=YZ;-b%HuRT;$ojUI-8GMV3~q<%pp!X z=HzlBbzgD<*{$sG-0AD~M2wKD&*%5MJe{4c$XZ|6<-;71v)usq?^I(PhUSF3_?{uw!Kku9CnC7%oP||R125-Ge@ayY{z3c0;*fVuknq}=mvsae~ zj3K^-Gb(gis<0Ma^0n)Shla?DO}0#4Iy$!uS_SZmn>SMk?(;>wYvEC#5tt`lCiv5W z9U}&)RNf2WX)tQDc*{z`-7tRo&0;YYgRgS9Ytnh4HOef(irW&#UcqQ$E#zpRAbaBW zwC{UT@b50=(PB6Ra87~L^uH=opm-enGk(ZTT=>{TypYpTq!939TemWhD3>vcynZ-= zSiqB?LIg7WPO*jCW%v<5Ts=llZ;vyO@i-!JtoBw^+}K0Oi1MK1-TnYkk!x=DMX$lo zK4Xc*eu`trlUn_raM<1F>FLo!vndIhg&C-~It#Dpjre^*oj8KaMci`$xbi-f$58z> zk5lAAGSuq#^$?)x2?D^iySw@y0|cdg2QcZ^q+ga8#3DCg}Wxis!1gSV?j!dcQ~YUX+X#C8rNY z*&&OY7<&#hCSSKcq9YsVbO<$}C1(suo}o@^+&{)31p6^d&QRP^%#6n>z)n{e{+gP6 zU>Q0Nmi_t?-2?3)dCY)VbGkiW8WRz#l_YDE(?Rll`im7cH+vxg%SShuK04RKy@S+{ zafp`D;J~4r8k^oM#bRv`fKbDu%cLm;i8jG|3!oN=G&S*f z^zG(*m=e5lm$jH-pKEngnTD$DQV+qSK0eai)K*9$^eahVes-bL zcyfBIpsTBiZCbGL{$sJqTRRPlQWJ#Yf=zrikKER+g6*y*j&@h)5PKVhZg+q78{}kY zJ1cpyrT8%TmDGaD^OX=neT3f^DgxmGC@EzlUty za%$*yp19nhhF`Xk+AIZZlL~lM6%_21d)hbP`Oq^X_iY^<_Wy9y}^0v{sEK^y^s2wgi%MQCn>##)c^hHMP?#8ne zseiQY$~tww9?|U%N%8W0Pnnv01k367C7Ls!;HWl1b84AeovR`0~exX({4$IdT zlY3nIpP!O>DA$_Xnp~@GAS1L@210F%WY32bFW4)%Alc_IHB#9f(o^lIP4+1slEW&Z zIIF0O4fJOl`z0fd$cpSHN0N@T3e#~sN}ho1qY!`LWG~9Tnvf(b3XGpJENINBPo7=M8CQPi%&Vw`Y z89sD=mgAgw%21h?G7MY37Gg%QzlwtSyBS|woPuk}L@Mact4YD2Pxh*({%eB&P_AHq z*g#bfhB-*eFlY_yT)zr-?^FE!-vi5B3`=6x)>6FoX2CW|1=v)ZPb_O0I=RiD#pY^# zjcb{?v~0?FBEjx+tR)3928=`Y<=6_c_d>GSw%we$*^{>$BG~=XDjgd%=6;CO5n3v) z$DHF=34{Fgh+9x&_p7xT&H=@9`^2UY?ZJRZ%3qq=u_cwplB&`%TO1?qH(4rh2@U>T z$kM@;)8vbU_KDy>Cu&rJnq$26CgZKxV)9@~D%Ut8 zkNE;~%#bSC%fo|F2|*X}Vhzi_D(d0RDymZ4%J@p_f!Z_8QP!;DYtktSEC z5!5ptK(L(-?UsT@7gDp;sO9Fy%8=0=(!=5QU?**o8X>{nA<^z0jG_ZXdaO#YSYGK~ z?!hj?`r3YMFE-Ba`X)zKk9x*ASG$zt%GjB^VWoG|obFaE$BMk(&Q33II}7Dp2u&2; z4Zmb2s2|Fu>(8D+&>lt8n3~rLrqPl2PwIyA5|N~d(3>JtlMv_(Qoy6 z4awQhn8p%&u~dQlA^B1C*-~BTN%kt(J#}d5< zl0^&iC}#U$4V@AQc1Z5A6w+eXxuwErOT~G(VPTdmHbQ;aSf3Dbu{t>!7dLtc%#C^a zVRc{FYV>Rvm!3SeaU)OhMqDj^|G4-Q@4wpZ!RgLQ94xt7!gJ@&%_ptPI0QG8k#3D_ zv^a!dJ6fyG{8pKLuT`|mNqvskAz}>vO<*n$W_3!+pg2`qj1ywDR<=^Cj@B%P*HMI* zgGEy^bw!UJbSdJ#;FyPFBeb59-J?=+tP&QK}?)Tp7oWI0DV@$CA68 z=;PxYo;m3iwDv~EB`0ll0?MvfEL!QoNyO+x1$)=xV3g^~8O=m3h@?!o#f#*sU{nqS zJD!3wg6GGPt2z-~r3ZTaIJ6M_<9;0a`sAJlw)U{oRi)i7ctYh2(H`V9bQm=$>qMHi zoeQPE1KBu_6;gBf*y3hUklxD=3ig^{f;QDBt#O`YC-!OwH*MTF{NM5?k=h>_+Qi}yX=w%Wggw)5j*qNi`DP`I6vv^kbhUO50Y_{{xDt=GA*jaVQ17@CsS(l zvFX=&tK772rJYFm@0dYrFghDfk`fv%sWwq3kxM|ZUB5vdLQ+iocraQ>Sco^{#k4}r zj%XjN?z1DBVEaMkXGJQ4nO#n4>5Ukz1||+mK-$)mr*8?$HPE$W5RKyXn&1~9UeYgB zIp|Yv-Y9c(d)r0uf=q5sveD4|S{yXeFPeXnkxqq`axcuu`hW%f!g8=bwP#D}(Jgp+ zmh4-w7sfDidE-FvGO5Dl()FoJ19?uxX&x3nS*L5__>(jE_R3*Ydy&>^b~H(b582V! z0e~yFWi~rYZ)>(b8*ke@ViY(1F~p47I6i=%7sr^ADmC(Ha!SsTE`OOXxXv|Bys+j+ z@TnGo=*a9?nB=y(>ZVT4jO@nJuW=^EWN(qt7nD~+WZPAqP`4f#bBY|D=7e{mFp;Jc zAJxS5S&gPVqn{HR{aNU<>S&_+Yzk|X5j!&ka~{uD;}u(Hq45;?>hpAT#H_?rJE$BC z0HKLo(?_Ew=eP<(>Urf^T7jeS=VQ<6b^=L)$=v6+9dl5h+ja!MVjT9eR6=!gwkn}o zpQTECPSeIbrv(3^QjKkhVkw!Elp+dVEVMq_&zV?8f*qOMoMet*4>)s@2NDCR=~GkK z>WG!oP6_T|sXY?Gmzik^4xQw_hAdU+O~%JbO|0DY%hukKmq9mmv@Ke2FnGBnq?1c**(MvQlr}I-*;Si{;&nu_73j3KaZ* zrspJsa}(m#IXK&qKCj`yj*qx(~*sjofQMM7N_B_qGwpDL@s%M5CQg$YvpMIle0 z9^y|X<5)jDhyPHZ$)1C_1tY3|6f10R@9IJ-Uu~)!v3f!&+&rmfe33HdN}28OtLbfO z13I}xY2iyW)=xh}vrh(6pY2PvG~;n6xJU6J5xT83byF$uZzgE~89neCBBrD;+1~oh zlf(TatF~6)yI~V3u&`R4I!Pu_HjtV*9py~LW4&Uo0Esz(7b)OE$vC^0s0iLdZ>=rh z;INvV*$QhJ%s5qA2lzV@&W@?-Iz`f}xIU#sa*ZOnn}*jwQ?Xgi(KHgVG825H?3sU8SjF8h^K>#Ahk7Jw_xR*^;Utyrb0e2#xC-3Tc7r=ZqRpgJNa*K9aP!Zj4R zC^SzZQ+|b_UN3KKBoujJlOEHGroCR8Kc8fL1)y}H)x1F6NI>?kLd^gH{S+|AO>08i z3Q!TPS3rFWo@>CHi|(ypN#?@NZ7(4`n@dY_b)2ZR2YY%Wt<(!4o*+<$69T;k5bj7h z_>hf10=UFnhbL0Sc!R7mmz*xArrQ9`TyX+~w-KI|S-aQjdL)sWK2lp13(QMRXgEh9 z*<6r}-czuQFo`kV1SqD+#w6Hk!d$qVw#^|HbFlmxK%HWj|;>j%F&7c>PUBUY@fRU!#0-L zr&Ji4x|1fVy)6Rq(gc*trMubj%shHW0C8v;c0)#>a}i)!3JRH!K<>@MC9jh`S?q8g zh|dNncl2EfO{p@8qZEM5oN}7t92;Y%#B9}+dR+&^+!^3r0G%4q*eJclsT^Do7$6Yc zFF&IfNPr z!7+~nrSrPXsBr}{<7x$aSv9f8t4y{VQ0MGmY&1K37T``nNa^5HnP92`HHufV0;xiY zR0RcjU)YLRlpRW${RBjWW>u*kRdOdG4w*F+hF%1ac;a}nc7fAKd~6T zW>JGx9~NZfAo!~Xkb#h$)Z!Mc#i%6FWN|^;3qUBP>pHkKuUqf|!2^JwYw>QGMc9#1 zn!^Mpk(e6D+IgpVYJLlr5eK>9YKx@hjIC;Nf>W$YrPw(r=xG>8l>z5{V6*wKVz|6B zllf=Yn zmj`6}M7Ea^Dw7c=Kp`f(LWO{U^j0}FSAtksfLvIn0!;C%sq=aRhhn@eX-|eh z-b6UHSvZiX17QInRD^L{Nkm%0j;cDUs-!B(m9vf=wVTmU>?+vBNi=E*I2`FJ9}Lvi zS7|$xJ)h&mQOm+?B;}H`(DE$gS4(K;_4UYmD`z5%NxY`@$uDegSM1se1cN9&OTLDxzm8Qj-){%Vz*29E3B@Z*(Gni^$8(wSlWe9c|woJMd zozW4nt3vDFLT_)xZY0<#f)&v;IDj7zu(*egrybCD30k78%K`q7z~y0iaRc`@95p8- zZG3HJaVZ1!VW5`<=zgrin9(QqcnGNfK0_2yt%+LqY6;`K$#Ly zwlXpj^tAv;B>{wNI*YWT3@;#kaCIB23`-jphm3%kLs;?M92n&%*o8TR7UhA=L9WFI z`$%;Hr#s@QtBHrGG#Ul&BW}ix-&mf~vSh^QI}??}Uw-s8Yx1HmL_;m=0{J_38ICEP zuL-QwLt!K6@mu%!?2-4YgugamNk5!}f$ECWi(6jZkwZm*7W58`g*)KY^#D)Pg=;9m^D@d$;IeR zXthxpAjYigT=u9o=VdkMgf@RlNeIpiVh4@CB&hc}?S2mdYrKAZKJKPZuR>vG?Ov*_ zmbLOjJk(_}hMiPdtCFD++CDZy2-r!tt6f8ngLqs;wips8+1@rC~X<L#kfdf+=->)ilBc3-3ODj zG7gegj)%csBaCXILE%%S;TZz#4XUo7>b$C#sY-@zd3VcB3c)*jK|1Cfr~l%Jeq7qb z3m{bn1&1^oE*mM~NmNYn1$_}L&lmeb;fVcz46sb+BxRQsL2R!eZ*nfj_MH~mA=6Gy zAIUr)IhuJsdeV9(iC58x%I!JHh=E^1HDz{<{4RS?@Y0yp>>I>Y;PgJh2hvz!)TFTl zyD2SblYeP?D!zG13vIICTTxsmv`Q3SpuKbdd(i%{;Iq@X z*Z;lrUZH&-IR7NHy(q#$`x**eXjcI1ldJJ_-;HRyK=2z-OcneYRO8F!KjUqh;79Rx zx!|WzxP>+&4d@`+yd<>e(unrE@&0GQdr{pdGy}!6LVE+n-wN&TfOilUhT@}g{QOby z`%ny2rI7`^3Y@f#N$t!{u+mzm1y507da3b~n<^LfevV z5bPJg*&wvLQT(gW{vFj@g?0zHaeom%EkfIc0z2{7qj+UHu$BvL8VZ~oe2U_$_@9cP zzzN>_D11WuavGmb^aB}J-J1Za6?_Yb-jDmSc!MB*hGL7*ev0B&d}M*TX9fSObcJ9) zO3%aI%>`Fpnc4z}rHhJ(8X-80Lrn zAC66c_k_@%N6{;^An;yk%n|6jo`OqUAw^YkM^`z`>L=m=OvIPFXy6a0I4#w`2`YGw;T&@i>y_l33@#YUmUP}6op`aQvu0CWrO zN)#aTI*KWR??m-G3-JsM-G^e2&<+B$6hp@`EALK!COA#TDL;PR?*zsUv`?dQOJ16~I}7~xatn*?_O^seA{q<<;+1L+Y3U&obY<+MtY~vlIbIYe+S4=`f?NlLK{RiB)KxZ zTxdVSGnPV_3_5dr2?g$3t_NO$;3R-A2#&$9_XRi7Fi+C`S%Uu>#T>z31Olvn6W(;e zNx}Y2Xh%_$2!0QW>oMPGd`57xj86o=GkqFP1t6$x6vZi=zyJ?E{2?IV6mSdPeknAf zUnR6x)0YXh3(xox2=w?eR~lOfa2O1qdqU#c4}=EY&@l4XP(Yv+=`wu12GkjX!?kH# z@Vii8XvY8?#;T|5J7E?c3e+Qh~mG zPn~n>)TvYFoH|u)ab>KpTknjQrWHy{Pc#+|D&W-h3C&HUK=Z^R{?JOkKEc0s!u&|MH>yXL`$L`K-j;AE76}Ie zdL)%hCAeR(A7wyN(dJpAhk9CLdQk9B))V(q1rqFc>l4L(x7!`RkujFow5gadQ>y z;B=a7B@Qt?vAtUlxfVveLEYsKx!N#FrSn4m1+)_jX_t9Bh9yjGPswpiXbE@ssd2a# zhkf3dKO8C~G8M2n15p!Ow&cy@*8VzD%z$KAJm2fPc32Ksyt0MiNUt~2IR@0y%k@Cm zI~wLNO19=MDzS;R0j z4ogrp6X%D+(x_d_R{5hY>Tk%-ax^p6G1SSmC&%ECYpYN<1%s%UG-?pT5#@|x7-4d7 zzT|p&z%u+VxLyV_4-RCW8pu30Fx(obCfgpAYv2UA78m*s?yUhO*Tl;zXSSp!JGA7u)LhH7k6eH;mbxHA61$Hx! z*tE%%f+Dt4j8v*WJ|5xmF3I>PG5-5s1bb3w*AruUrax4S6Qz*D@ACn(h-9s{Wv8rz ztxuGZp!hHG*G;@Jbre1E`IKfL^0$NoVGKFJeWi&aLV-Y@z9{HOpemnAY9v-F@!8Iz zgx1xyZr-#VJ2~Qi@>nXJ_~ci_c2+7Om7>H|3iJ3VA0mYb_WSqKMHtYHYCt6Ov4B6M6FJ6$ zF*^WUPAMiZAlolWBru<5f;RR2^tgW653^?LPUu;%J6U?1snB9*)6F=trb_6fs|){{ zn*5NtUaB^rU#fdyD%AHBm`8c8^y7&yCyw=!Z+*H1e8n&UyQJ;4z2+;L>kBqM}7V^u8H-86INs&G)B5z=E(pSN3|;R^?6wzZrS z>Fhea4GCFlUCUQKn^`AHUoB8iiyjC}kv6|fUlUvC*8`mdx>&BJW*?VmGVsRYlaIv&lq^Fnqk%>q8XsB2#3t^EH*Y}^1DEaoeb9~p7V(L!9zvG{?#jJ<< zn4fhrFS~?A@EO8)9jtg)XOO$8}1vKns8ckNnQ`j657Smw(ykJRSAU3hbBp@F&CFwetJZ( zm+GW}=GjDjrDQ^%k_GHy4?0bzOAz*9`XebCMM8Q&!KI$miirXsoznbo(qa*`e#l?-V(O)<}1!=cPcSi@}$`z83fzP z>cFi|@sgvX*pfKqHyCA6Pb82MY;zrLXI=Z$T6ui?nU)DAO%o)0-pW&7by(|k8_9iu zoil@s&@GMd>oqX4!9pX;(FBdlP5*2oo1HIqeXUd-eM&VzbY)O;VFMR!x%JS~as`t8 zkP@u{bD_DRZfQMt)D}|CTh%i_*27Zi`RN5iT2B)Mqp4byUW_NO4pvmu)y4OZ#cni@ zX*j8m&y0@)1?Mm*6(O+IE=?cpkDo-c!e=6Gm8aWtjHl{;%u0i`wTL=`P^u<hH?G&j&Jf%iF7=y=Ql|u}eTpft$Q<6xvldEed@3iWje~@J=&z4V3p3SyR zQ(?-g6|J&O&@NAZ%d*XTOcz4W^ihaMQ{9p7#1mMsP0OdH6MrJ}(qIx~Ubcg! zCW#>|m1%~}6Up79Fg3p?77K@19Wf*`z6-u2StGQ@lMx?JKFMN5t_%doXB7d(-Fc_M zk?`Y8(os|^Rc)!UPiM6`oyE|Bn$FdU@@UjA>r+_XPfae3k6YmWd^?gwmNIKfl^y1e zd~RRLDOG@=wZ@KRArMVXO1#v%_>*-W3iYa~rn9d0(=_zTrA7(>wjK zVY|Cx==m9Sd~1j6uDlb~nV4>ONG4ejHILD%$GZPG19fLZWjR?A_8_tvNV)Avb!own zgjSj6r0mAp!00g;QVA-e_<{{YD?-$!O%su!`2#w6k?7KnFbY}AP=ZaRY6QD&Q4?c} znuw+9-!w(5N3z7Jr|*k1SR!&ORdz(e-Q3+B@T&@3E0QUh2qcR9em|s2A!j3-kz$@| zS-s%@TD8o@*fLjMXSQC?ryh{KwJ%E9HX~SCYL&-RaWYh-6xAqyp4C4Ex#q0%Rj%29 zK9Fl(io7zwuE%E#8K;kV_gf19Ygn0azDQML6REVt8}jJ^r&t^F#X32KEFmNNQ5zjA zy`G#mVabx<@=1&>pOmKuWUz9*7rT`nN-2|Xs&IC?`2hQL1|}-On^56R2)0Ej*|LRX z$z@|=UD<--dkiJvP%i(iCjVD+xK~(H=AUj)xAW-< zG3X?JS9MM{zb~hDmDwX7PbZ}qazC^*+@d-6`P-yp2zNg#_)iw`cquGUc}jAZWQ1c3s}3_X3vvv6D%xYK z)b=o{g1un(!A@mSE?dG|U_0PPl30#z zfBYg$o?!PQRd?7+R&($Gg11d4-L*~6)176Ia!#@GmbQ7X_pkI~-{NhrY9K0$DXQO z@F%cQBH`$%92Dh&aeDwO&J+AHlw{~LPkhs_NS{(~RHpA}=I~(Vp@9r`0QBB*Y{ZnJKR%5XB2p49osb!BHI=rPM#5|Qqz@MC zhs3-;UTiK{IEb5H95DhEYjrq{sv{4z*Wv#KyEV_{m#++jJML7S?G~I^ZJCft#3Tu4DWHKl`sf)@BkO= z=Ysu0c>~g$1{N2?*@{uT%wnFrwW2;l}g4lXV*va&@{2+$dY6daEp10TF8q)R?Yb-0p`g8Q`2%#hOJVXe6 zKEHQ6ghKn7XK;A2Wec60m?yAX`^%_8F4!UIBFpH+ainsx6S+d2%8eO+(vmPvOu?Pz zWTc}_Sz@ASsRWC=vGfWLPxG*7P~|Owa8!2T^y-Yfy7N4iMmu(QAE=YkD{!1XEH?`?z7IS`8NT9I)Y20hm7Nr4)Duv_ z6w8vOUX;kk#I$sQOvp#Y9s793asVrJE~A0;;&9A=gf$<}mLmXpKP@_~Ipw@`@Ri zsGqH7e_O3JKVoFskl8_CgHeC^cd3JuCT01`corZfel%(SI@(c7=h=fdcKimUt2a~;y%IT5 z;`4QO`heS6EQ5^DMDY#Saotdn9oLBQfYgJnh%Gy`1IQ>_5mBUZYcrCgJ;!DQ^+WJ_ ziK)$p8Lx(!S1bF+6z3k{+hk5t68!wENsKpbk`AXaOVTdM9jdDdbO~S<=~+&R;IoP0 zgtLV9iQo^={L>Soci32igP|AaDNG`slD6@G(=52EM*qooAc@BwuhU}%@JT#^Y zp61o6BxRv|IdGnY@zkiremzJ=!GOd3>{^|&~(9WafYE=&=nR2 z0@;Fyw^xtw57NoqFev=R<6iugv8(oHiQ?AQt}czST2s#?VkLcCsK&dMlAKDYiBBQu zLadz3;}|4~UZbrRJf-}T6rDguz5tN^wCpCLTFhOO8>JH~M)|44dk5NcH zCNuYUWq{|+SY?@ek$Ul~Fr9dORZY!I^;k^JMI7+)G&P4XDeNdwJ~5CPAmL9S@YfuoghW%4^!|q4zCG*-~<^ZZNe1__Cj+(lUlpr-E;48%Lv<(?f%>JxMkw2$0 z$3DzFOa+{mX>9KeWj~|)^RHHA^`A9Rt*yP-vI;{Y_LKDy1M!SV4tE>rBC8|7y$D^u-Q{1pwJ88 z>f#8wD{2CiZ3YylN_I(R76D%a&_0_Y!1Dm$E{^I1+}>1FwrrB>5P%pC0f~k#%2ay% zojM|>bdZo?1z^=y5yrDh*JHrsbp&;cRLaZlBzlKrgt-tfO*QXPL|MThLlI!MLf=pb zwv0*(C4eH|HIoUcAjR))h3=>X(;(gkG{Yk8D_ zmMJLv_z<9K(_&2bpJ^vpUiX62J*P4gGnIJ=Z~2q7RncY5L#}~|fI`l!VjF4fj5^Ly z(OZhz#-nwG)C5Iinb^cqz)+smv>Q&l%5Z02~YYKpqomG^Y_0+HRNv!qo#(LQ^9r>>%E9 z*W->nHl!prSb*j>Ax;b52$<8MAS3|dTpf*#=Yk(`tCf~!OD22y1n?Zy$RX4Kny2>t zd5FpjoC;`;f+_*XTZK4q&z+%<6)T79NM$wvRz*jrXGdM_y~x|h7>HT*{3S9uToY41 z0ud9?GBeJTqTa)Mjto%%oH}_O?|Gv^I3XnIq!#0X9rbn|Aaa&SF?>$W+nIRFT^VZ? zM48IDqzw*;TDw+Ukc`GFu)PEt8=>Nd0nAZ5P>AUp>$U=y`df zhZY-Fza9k*pPHDeZf^vMyjj5@ru=!?s=}Dhk>{I@8x&z_ulyO2JUj!*1|%8~vLR@B zHgn4;9bA@@{8vrTbYLpm%yN)XGRr}R$y~wE3oVREb}tg=ipv+PQx)`+NZ?3c4VHf1 zWRDqo5d4K*2=QdO^|+F22`X7MSyEtdgfNcoCE!30R{@ktFls;GCtI>x(IV=|{!CP0 z5{naqIk_z)v3_rrWl1Zo)?#U{FS|!_loPE+6&CVP&=W<`s-W{4m&x6u1g_}JZYgqG z3Wf*@TEN9Y%3~z%;av~XNJ=_z-PhF6;av|&{dB3H{n*fl30fABzwoh@iRqF#Lr^9S z(jQo3mr)@|VIc=B18h+Gy&O2wQSdJhk~7RU9EPQyN*y=LDa;jN$0mY21XCCbR}v|FAgNq>-Uld9xXj zt&ON@Q)pAN+AV8UOP#vTV=oS~T@IIGb%S%b@>hEu;WcDy@-jl}{7dyfx4mTHrYL+< z(u(raGJiLSyzK&729Cl+Al`U8{%2(3Q4D%_i8*cG<* z(Ki|b_A+Gf#lD`HO@ty5!AfWf9KeqVSlUfTbPnhz1T9nR$pQY9z!g#Xn@0Sk(b4ju zO}5!7-8&>p zWJ#oc&UaLEH#*-@p2lyq9s&1czu?6Q&5eC$v(Rodgw`Xp8w^0*`2ID){|}D~g;tIV z^}9k_ZwUU}NdTd{AL2WT?3du}W}#((a8ziw0XRo!*Wv90!Gmb~jnJOMZJ zP4NE)=rqBX8vBK|-`Fd(1K@%*E``TAg1?Q&wL)tG*40A$9^R%3egtngv$+gxHsXLD z51bR-3ZQSYaY*p}02~oo+Q8Ak1IEXKQGZ(nPXnV-XuHAWWWis;V+p>Y?f4XY|1Y6E zgU4MMD?oP(zQNcfw0l6aSZM2vXVHY_?LvDHAY3(vmf2px@up$yv+($)(CW~3mC(MA zw|1d{EsE-V6M#_T8OGCspNkfV{(FGl>csc!gcdSZ3%<+PEI3A~;iThTJkG=a$O8{# zy#Ef=m*?U81i^RWajM|2;;~X_&@l{v-)6icv|j;)i~gqp8A;bZJpPC+6o5i#Kft43 zX!isC6Tz=D1_YmKJc3FmuyBU45X}QZdm0bC{f~hS!*1h2lyHsbFkayNMerWb-Y+-| zN5d37Z*&Qc$>rKv_;|G$&|cUEaQ-ZKH$c+_zZ^guqx>Cjhpxu=a>0}MUU`FY3{nH| zeW4`)C?O#)5?Tcw95;f%1e*9M-WCb%Bs^M$HraSn@Mny-g!XGR<3Y_np?$-6OlUA5 z?G(XZ0WTz^dyQ?FN?^U?4R(gGZ6zm~9TtFEX&uX%@~E{3AS8;G2P?ou3&G3;uQEJFq2V5L-nw z-6}Lpyrv6n4j#LO_Jr|-;OBt(L1+f-rVD;4S~dvn7kJz&v?l?4^D2D&P4MgSm<_d} z1!H^>k4J^}f`KjDy~aYJ{S3|j#PKN}xa9IZG~*O%opFKCHXD7g7o$ipGF{}vkD&1a z!T*7`!Bg;2AvpA-A=SAZZ+<@nN}>th--hbZQZM)p0H4Qsvhldko-*3uT#RRgwhxUh zLaR1jhx-7=r-Fw7x?gC&#p9PS4KSH0G;$6*AvfM2Y8-D~q0I&XBwmTPbwaxdZ-dJW zXysmD9Tog^<2|8Kw|LM>hM}$jYMJ0L63vex0Js3=jK>VHHxA&5mTzOl0CXPK8;B1H z?G^)*emB0~B={{r*e5iMO}h+6g2xYp_9Hx&!%^Y!W1(#X<{rWOjS?6*7@c1O_+-Ip zF8(0c0ld`;zQypsfB?cVC5`o0m<~KP3+(~pDU2CRQi9)XU=qokR$Oiz5&U<+m8zl#f~?O$2V|+2}DN%#v6h^g?3E;YU3fnzh)d3+Cyl%5Izuy zVWG{%<2IpT=Ge;m@>L6M?M(6Vg2xr1Sh*`7FreFrU*_${p8GSNWvGA77W^BTO8j3rkeId3ZwdRtUKw + + + + IBDocumentLocation + 240 146 356 240 0 0 1024 746 + IBFramework Version + 283.0 + IBSystem Version + 6F21 + + diff --git a/camino/resources/localized/English.lproj/Keychain.nib/objects.nib b/camino/resources/localized/English.lproj/Keychain.nib/objects.nib new file mode 100644 index 00000000000..e69de29bb2d diff --git a/camino/resources/localized/English.lproj/Localizable.strings b/camino/resources/localized/English.lproj/Localizable.strings index 6e0da7d528a95cb399a9aff4a9259608095320f3..da2b9bebce24edf2e956c3448d378a71b86ab192 100644 GIT binary patch delta 923 zcmb7C!AiqG6r7WShf)w)2#VW64|?&eA}AF^5TUl->LHpCf=ODE29NOzyyWWHv*67y z@gqF=0fNrkDrwVAL6+TQcix+sefvK8Z`Uv1R__8X?xApk5x)@ver-5B86)Pu$JIr` zp?K;OlL(Ky9qeKa?Q&-RWVQ0N(b!XJ105WxO~y``Q|#L~FlB0{2<|UK{n!;B|7Ph^ z&E`yzGv*7Sg2lJ8Js}5a?{=2p1FJ^U#hOA1!dQ3PS-d*94vkenwzGIi(BHS`R z&`eJLxYEp~Z03wJ#*1Feky5{`U4@(3L_eT@%2lf5lika7DdOp7=2}+-?>MKeQT1$> zG#8Rgs5BkUxx3L IBDocumentLocation - 237 33 482 372 0 0 1600 1002 + 105 33 482 372 0 0 1600 1002 IBEditorPositions 266 - 437 533 277 90 0 0 1152 848 + 644 623 277 90 0 0 1600 1002 29 11 957 446 44 0 0 1600 1002 494 @@ -31,7 +31,11 @@ IBLastGroupID 2 + IBOpenObjects + + 29 + IBSystem Version - 6F21 + 6G30 diff --git a/camino/resources/localized/English.lproj/MainMenu.nib/objects.nib b/camino/resources/localized/English.lproj/MainMenu.nib/objects.nib index 639e9548c05f38c2cf97a01023d85045e6f7e550..9f05349791e4b9575af6908df77db58ebcbd89de 100644 GIT binary patch literal 10767 zcmb_i4{)5tb^rD(%la=_HjWJqIVLcKK%l@B9CwT*%g9z`%Qk1?76+Kq-6!er-F=t4 zlV!yP=ZU*ZJG2wx*gK#oQ~PACX0mBJoS+#WSFWc@sstLX_Dh?U=FNIC{HStntD*KE%P+L*PuC$wrX8}5zUp=>&q>=&BT{obAv z*EaTq+Eb}`EE3MfoMa(i$cb25g0l{sc5<*QYbQwj?{=P~+JMOV+4fvjtgWrh%02pM z&8l!L$&>}7hC5w*IvpOia=BTMuRphs)@;jtciUL55u9CJ%-*&rrbX2Dgg3?d!&xU? zfIzD-VzpS-$kwxG¹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 literal 10741 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 - - + + IBDocumentLocation - 94 26 404 250 0 0 1152 746 + 24 42 592 284 0 0 1600 1002 IBFramework Version - 248.0 + 286.0 IBSystem Version - 5S60 + 6G30 diff --git a/camino/resources/localized/English.lproj/ProgressDialog.nib/objects.nib b/camino/resources/localized/English.lproj/ProgressDialog.nib/objects.nib index 6377ab6fd1971ee745a4b555450a7e8e034bd5d1..7e7c0487fc172fdd6daf85bbab32eb6211c1dab8 100644 GIT binary patch delta 981 zcmY*YTWb?R6rRbYm!#NM@S&h3cp(}D(I?4+U91%GAwpB^qlC>ymu|8(jiy>`oOE{I zgl4u`GEJ8@3L##!z8nb9V5cr}6$ats*51W|$)Paq^#=2#(o z7T>Vq_`>x*2_YJiV9-V*G4)U>DzOaAf*#ArCH09C(~B`#&(CT~Ny)~tdbyzKne3b; zMBr=%6S~Mt25(0|7sr0z6=|!~STD$mMWz!APKrXj5mU!o4)1;ej z&(?d0IV9_a5~MPv%$IxzaTMG}aK~f@#Yw}200!UY=>6^2US9Q1TXK05IfuHhOmKU zbo_R@l#yqIn+e}NskHyL;lBV>i~C={3rIMTLc=;!B8VGs=yYRj@@#s^>AX81Y{DJ?rKt< zorh*>H2QBHcFEsxLUs&HL&6{E^hhN5&&AsWU!G(J#IM_JZaWZoO}h=IkkG-p(|bO+&coKD-Yb=@j=0*FRW#*6 zrldd{(QjLIAFJHO>RN<%B!47p*UG^f%^&?;`|g6>P(Gy}rY3m$Ey|-bAgQ|x-gkmt qdVAy|vOG@EiuaSChSws9d%p-;_3GGjo_U?8UYj5W7n;^a-^hO^ER0{D>#4P8>_ahc-Ru1@LNyiN**>+<}lrW(2?%S5*=n_{WU0rw7$&yp2m zOd@jbB}%Vwe8cS;r3sFIPa?}O1FvaPSk%-U(NVcXACxQ?(asEvd}9P5-CQz+IhhRW zy0D5UeU9UUY1!>4(a%brTZ|!uJPSt8T|S8rpDcMLi~Z4Bu-*H8`FmIZ62fqtvBMq9;9 zhJ^|#j%u<7wA2!`HCQ{ruNDlV*bqji7_eUVvFUoPmA2&b_uuZXtz(-#CpI2}TX(~a z)gpA=MBrlsH8^eA4gOl1{N?YOcorCB*CvNwF#5jysu)Y13>Oj5@iky0`y0zzuZO+$ z5Y;vT@Y^%EupA~T|GOY(U`=irSUWF#0?pNz)zTsC_A_7?E&&Qb^wf$s3WR_nraTe+kg!4Ov($kX#=FkEXu=-@y5P z6FIEraJ^7-R;Fgn;{yZffq{_DgD57YFK~QQ7{=9{BnpP6o9NL4wn0bg4F;Xv4o>_{ z0mNjbrwqF$HJHDJ5p);~jB&Utq#Gul>1CZb)7y-S#zirg6A}LV1YK<1h5uK-qe%2F zY(ooU6aQqQ@7bE{9wg9M&nwwlQWCCids&LG*{{OLl@WPuj zTTgkT!g5b6*Bbz|nEtYH%z|vo5t+XqN3AffI+f7-J(f;u(cfWW&i!p{L|hxhkC^pE4d zd)q(y*#A}V|5)&!ioTcd*QWfv5B#ln{exM*g8kjBzdh~$dB;Ee$bT~F|2F6Up7Vd^ aT-ik>SfYD;WK + + + + IBDocumentLocation + 75 299 448 284 0 0 1600 1002 + IBEditorPositions + + 27 + 573 628 420 80 0 0 1600 1002 + 5 + 573 564 420 208 0 0 1600 1002 + 71 + 573 564 420 208 0 0 1600 1002 + 97 + 573 628 420 80 0 0 1600 1002 + + IBFramework Version + 286.0 + IBOpenObjects + + 5 + + IBSystem Version + 6G30 + + diff --git a/camino/resources/localized/English.lproj/ProgressView.nib/objects.nib b/camino/resources/localized/English.lproj/ProgressView.nib/objects.nib new file mode 100644 index 0000000000000000000000000000000000000000..3484f9a67df6ba9b1a5fe816af398f69b3d5cced GIT binary patch literal 6197 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 RQAzH}B{R~9l6za%{|gY^@?-!2 literal 0 HcmV?d00001 diff --git a/camino/resources/localized/English.lproj/alert.nib/info.nib b/camino/resources/localized/English.lproj/alert.nib/info.nib index 1f32d25ff16..f8aa8787f47 100644 --- a/camino/resources/localized/English.lproj/alert.nib/info.nib +++ b/camino/resources/localized/English.lproj/alert.nib/info.nib @@ -3,13 +3,9 @@ IBDocumentLocation - 410 67 356 301 0 0 1152 848 + 325 55 356 301 0 0 1024 746 IBFramework Version - 286.0 - IBOpenObjects - - 251 - + 283.0 IBSystem Version 6F21 diff --git a/camino/resources/localized/English.lproj/alert.nib/objects.nib b/camino/resources/localized/English.lproj/alert.nib/objects.nib index 6a8f50daa6c40b62549d50aec75cf7a65de2a725..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 14759 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 diff --git a/camino/src/application/AppComponents.mm b/camino/src/application/AppComponents.mm index ebe8a06c200..d8cf7b31b10 100644 --- a/camino/src/application/AppComponents.mm +++ b/camino/src/application/AppComponents.mm @@ -37,10 +37,14 @@ * ***** END LICENSE BLOCK ***** */ #import + #import "SecurityDialogs.h" #import "CocoaPromptService.h" -#include "nsIGenericFactory.h" #import "KeychainService.h" +#import "nsDownloadListener.h" +#import "ProgressDlgController.h" + +#include "nsIGenericFactory.h" // {0ffd3880-7a1a-11d6-a384-975d1d5f86fc} #define NS_SECURITYDIALOGS_CID \ @@ -55,6 +59,27 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(SecurityDialogs); NS_GENERIC_FACTORY_CONSTRUCTOR(CocoaPromptService); NS_GENERIC_FACTORY_CONSTRUCTOR(KeychainPrompt); +//NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadListener); + +static NS_IMETHODIMP +nsDownloadListenerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + *aResult = NULL; + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsDownloadListener* inst; + NS_NEWXPCOM(inst, nsDownloadListener); + if (!inst) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(inst); + inst->SetDisplayFactory([ProgressDlgController sharedDownloadController]); + nsresult rv = inst->QueryInterface(aIID, aResult); + NS_RELEASE(inst); + return rv; +} + // used by MainController to register the components in which we want to override // with the Gecko embed layer. @@ -83,6 +108,12 @@ static const nsModuleComponentInfo gAppComponents[] = { NS_KEYCHAINPROMPT_CID, "@mozilla.org/wallet/single-sign-on-prompt;1", KeychainPromptConstructor + }, + { + "Download", + NS_DOWNLOAD_CID, + NS_DOWNLOAD_CONTRACTID, + nsDownloadListenerConstructor } }; diff --git a/camino/src/application/MainController.h b/camino/src/application/MainController.h index 2bf9fb1ce2b..33edbca4a3d 100644 --- a/camino/src/application/MainController.h +++ b/camino/src/application/MainController.h @@ -52,9 +52,8 @@ { IBOutlet NSApplication* mApplication; - // The following two items are used by the filter list when saving files. + // The following item is added to NSSavePanels as an accessory view IBOutlet NSView* mFilterView; - IBOutlet NSPopUpButton* mFilterList; // IBOutlet NSMenuItem* mOfflineMenuItem; IBOutlet NSMenuItem* mCloseWindowMenuItem; @@ -137,11 +136,12 @@ -(IBAction) addFolder:(id)aSender; -(IBAction) addSeparator:(id)aSender; -//Window menu actions +// Window menu actions -(IBAction) newTab:(id)aSender; -(IBAction) closeTab:(id)aSender; +-(IBAction) downloadsWindow:(id)aSender; -//Help menu actions +// Help menu actions -(IBAction) infoLink:(id)aSender; -(IBAction) feedbackLink:(id)aSender; @@ -154,7 +154,8 @@ - (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost; --(NSWindow*)getFrontmostBrowserWindow; +- (NSView*)getSavePanelView; +- (NSWindow*)getFrontmostBrowserWindow; - (MVPreferencesController *)preferencesController; - (void)displayPreferencesWindow:sender; diff --git a/camino/src/application/MainController.mm b/camino/src/application/MainController.mm index 9ef0177d9bf..e200d2f2e43 100644 --- a/camino/src/application/MainController.mm +++ b/camino/src/application/MainController.mm @@ -260,19 +260,7 @@ const int kReuseWindowOnAE = 2; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - if ([ProgressDlgController numDownloadInProgress] > 0) - { - NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?"); - NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @""); - NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel"); - NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit"); - // while the panel is up, download dialogs won't update (no timers firing) but - // downloads continue (PLEvents being processed) - if (NSRunAlertPanel(alert, message, okButton, altButton, nil) == NSAlertDefaultReturn) - return NSTerminateCancel; - } - - return NSTerminateNow; + return [[ProgressDlgController sharedDownloadController] allowTerminate]; } -(void)applicationWillTerminate: (NSNotification*)aNotification @@ -439,7 +427,7 @@ const int kReuseWindowOnAE = 2; { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) - [browserController saveDocument:NO filterView:mFilterView filterList: mFilterList]; + [browserController saveDocument:NO filterView:mFilterView]; } -(IBAction) pageSetup:(id)aSender @@ -584,6 +572,11 @@ const int kReuseWindowOnAE = 2; } } +-(IBAction) downloadsWindow:(id)aSender +{ + [[ProgressDlgController sharedDownloadController] showWindow:aSender]; +} + - (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost; { [mAddBookmarkMenuItem setEnabled:inBrowserWindowFrontmost]; @@ -591,6 +584,11 @@ const int kReuseWindowOnAE = 2; [mCreateBookmarksSeparatorMenuItem setEnabled:NO]; // separators are not implemented yet } +- (NSView*)getSavePanelView +{ + return mFilterView; +} + -(NSWindow*)getFrontmostBrowserWindow { // for some reason, [NSApp mainWindow] doesn't always work, so we have to diff --git a/camino/src/application/nsStaticComponents.cpp b/camino/src/application/nsStaticComponents.cpp index 1065d7b5ed2..849cbfddf5d 100644 --- a/camino/src/application/nsStaticComponents.cpp +++ b/camino/src/application/nsStaticComponents.cpp @@ -47,7 +47,58 @@ NSGETMODULE(_name) (nsIComponentManager* aCompMgr, \ } // NSGetModule entry points -DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsUCvJAModule) DECL_NSGETMODULE(nsUCvCnModule) DECL_NSGETMODULE(nsUCvLatinModule) DECL_NSGETMODULE(nsUCvTWModule) DECL_NSGETMODULE(nsUCvTW2Module) DECL_NSGETMODULE(nsUCvKoModule) DECL_NSGETMODULE(nsLocaleModule) DECL_NSGETMODULE(nsStringBundleModule) DECL_NSGETMODULE(nsLWBrkModule) DECL_NSGETMODULE(nsCharDetModule) DECL_NSGETMODULE(xpconnect) DECL_NSGETMODULE(cacheservice) DECL_NSGETMODULE(necko_core_and_primary_protocols) DECL_NSGETMODULE(necko_secondary_protocols) DECL_NSGETMODULE(nsURILoaderModule) DECL_NSGETMODULE(nsPrefModule) DECL_NSGETMODULE(nsCJVMManagerModule) DECL_NSGETMODULE(nsSecurityManagerModule) DECL_NSGETMODULE(nsChromeModule) DECL_NSGETMODULE(nsRDFModule) DECL_NSGETMODULE(nsParserModule) DECL_NSGETMODULE(nsGfxMacModule) DECL_NSGETMODULE(nsGfx2Module) DECL_NSGETMODULE(nsImageLib2Module) DECL_NSGETMODULE(nsPNGDecoderModule) DECL_NSGETMODULE(nsGIFModule2) DECL_NSGETMODULE(nsJPEGDecoderModule) DECL_NSGETMODULE(nsPluginModule) DECL_NSGETMODULE(javascript__protocol) DECL_NSGETMODULE(DOM_components) DECL_NSGETMODULE(nsViewModule) DECL_NSGETMODULE(nsWidgetMacModule) DECL_NSGETMODULE(nsContentModule) DECL_NSGETMODULE(nsLayoutModule) DECL_NSGETMODULE(nsMorkModule) DECL_NSGETMODULE(docshell_provider) DECL_NSGETMODULE(embedcomponents) DECL_NSGETMODULE(Browser_Embedding_Module) DECL_NSGETMODULE(nsEditorModule) DECL_NSGETMODULE(nsTransactionManagerModule) DECL_NSGETMODULE(nsTextServicesModule) DECL_NSGETMODULE(nsProfileModule) DECL_NSGETMODULE(Session_History_Module) DECL_NSGETMODULE(application) DECL_NSGETMODULE(nsCookieModule) DECL_NSGETMODULE(nsXMLExtrasModule) DECL_NSGETMODULE(nsUniversalCharDetModule) DECL_NSGETMODULE(BOOT) DECL_NSGETMODULE(NSS) +DECL_NSGETMODULE(UcharUtil) +DECL_NSGETMODULE(nsUConvModule) +DECL_NSGETMODULE(nsUCvJAModule) +DECL_NSGETMODULE(nsUCvCnModule) +DECL_NSGETMODULE(nsUCvLatinModule) +DECL_NSGETMODULE(nsUCvTWModule) +DECL_NSGETMODULE(nsUCvTW2Module) +DECL_NSGETMODULE(nsUCvKoModule) +DECL_NSGETMODULE(nsLocaleModule) +DECL_NSGETMODULE(nsStringBundleModule) +DECL_NSGETMODULE(nsLWBrkModule) +DECL_NSGETMODULE(nsCharDetModule) +DECL_NSGETMODULE(xpconnect) +DECL_NSGETMODULE(cacheservice) +DECL_NSGETMODULE(necko_core_and_primary_protocols) +DECL_NSGETMODULE(necko_secondary_protocols) +DECL_NSGETMODULE(nsURILoaderModule) +DECL_NSGETMODULE(nsPrefModule) +DECL_NSGETMODULE(nsCJVMManagerModule) +DECL_NSGETMODULE(nsSecurityManagerModule) +DECL_NSGETMODULE(nsChromeModule) +DECL_NSGETMODULE(nsRDFModule) +DECL_NSGETMODULE(nsParserModule) +DECL_NSGETMODULE(nsGfxMacModule) +DECL_NSGETMODULE(nsGfx2Module) +DECL_NSGETMODULE(nsImageLib2Module) +DECL_NSGETMODULE(nsPNGDecoderModule) +DECL_NSGETMODULE(nsGIFModule2) +DECL_NSGETMODULE(nsJPEGDecoderModule) +DECL_NSGETMODULE(nsPluginModule) +DECL_NSGETMODULE(javascript__protocol) +DECL_NSGETMODULE(JS_component_loader) +DECL_NSGETMODULE(DOM_components) +DECL_NSGETMODULE(nsViewModule) +DECL_NSGETMODULE(nsWidgetMacModule) +DECL_NSGETMODULE(nsContentModule) +DECL_NSGETMODULE(nsLayoutModule) +DECL_NSGETMODULE(nsMorkModule) +DECL_NSGETMODULE(docshell_provider) +DECL_NSGETMODULE(embedcomponents) +DECL_NSGETMODULE(Browser_Embedding_Module) +DECL_NSGETMODULE(nsEditorModule) +DECL_NSGETMODULE(nsTransactionManagerModule) +DECL_NSGETMODULE(nsTextServicesModule) +DECL_NSGETMODULE(nsProfileModule) +DECL_NSGETMODULE(Session_History_Module) +DECL_NSGETMODULE(application) +DECL_NSGETMODULE(nsCookieModule) +DECL_NSGETMODULE(nsXMLExtrasModule) +DECL_NSGETMODULE(nsUniversalCharDetModule) +DECL_NSGETMODULE(BOOT) +DECL_NSGETMODULE(NSS) #line 52 "nsStaticComponents.cpp.in" /** @@ -55,7 +106,58 @@ DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsU */ static nsStaticModuleInfo gStaticModuleInfo[] = { #define MODULE(_name) { (#_name), NSGETMODULE(_name) } - MODULE(UcharUtil), MODULE(nsUConvModule), MODULE(nsUCvJAModule), MODULE(nsUCvCnModule), MODULE(nsUCvLatinModule), MODULE(nsUCvTWModule), MODULE(nsUCvTW2Module), MODULE(nsUCvKoModule), MODULE(nsLocaleModule), MODULE(nsStringBundleModule), MODULE(nsLWBrkModule), MODULE(nsCharDetModule), MODULE(xpconnect), MODULE(cacheservice), MODULE(necko_core_and_primary_protocols), MODULE(necko_secondary_protocols), MODULE(nsURILoaderModule), MODULE(nsPrefModule), MODULE(nsCJVMManagerModule), MODULE(nsSecurityManagerModule), MODULE(nsChromeModule), MODULE(nsRDFModule), MODULE(nsParserModule), MODULE(nsGfxMacModule), MODULE(nsGfx2Module), MODULE(nsImageLib2Module), MODULE(nsPNGDecoderModule), MODULE(nsGIFModule2), MODULE(nsJPEGDecoderModule), MODULE(nsPluginModule), MODULE(javascript__protocol), MODULE(DOM_components), MODULE(nsViewModule), MODULE(nsWidgetMacModule), MODULE(nsContentModule), MODULE(nsLayoutModule), MODULE(nsMorkModule), MODULE(docshell_provider), MODULE(embedcomponents), MODULE(Browser_Embedding_Module), MODULE(nsEditorModule), MODULE(nsTransactionManagerModule), MODULE(nsTextServicesModule), MODULE(nsProfileModule), MODULE(Session_History_Module), MODULE(application), MODULE(nsCookieModule), MODULE(nsXMLExtrasModule), MODULE(nsUniversalCharDetModule), MODULE(BOOT), MODULE(NSS), +MODULE(UcharUtil), +MODULE(nsUConvModule), +MODULE(nsUCvJAModule), +MODULE(nsUCvCnModule), +MODULE(nsUCvLatinModule), +MODULE(nsUCvTWModule), +MODULE(nsUCvTW2Module), +MODULE(nsUCvKoModule), +MODULE(nsLocaleModule), +MODULE(nsStringBundleModule), +MODULE(nsLWBrkModule), +MODULE(nsCharDetModule), +MODULE(xpconnect), +MODULE(cacheservice), +MODULE(necko_core_and_primary_protocols), +MODULE(necko_secondary_protocols), +MODULE(nsURILoaderModule), +MODULE(nsPrefModule), +MODULE(nsCJVMManagerModule), +MODULE(nsSecurityManagerModule), +MODULE(nsChromeModule), +MODULE(nsRDFModule), +MODULE(nsParserModule), +MODULE(nsGfxMacModule), +MODULE(nsGfx2Module), +MODULE(nsImageLib2Module), +MODULE(nsPNGDecoderModule), +MODULE(nsGIFModule2), +MODULE(nsJPEGDecoderModule), +MODULE(nsPluginModule), +MODULE(javascript__protocol), +MODULE(JS_component_loader), +MODULE(DOM_components), +MODULE(nsViewModule), +MODULE(nsWidgetMacModule), +MODULE(nsContentModule), +MODULE(nsLayoutModule), +MODULE(nsMorkModule), +MODULE(docshell_provider), +MODULE(embedcomponents), +MODULE(Browser_Embedding_Module), +MODULE(nsEditorModule), +MODULE(nsTransactionManagerModule), +MODULE(nsTextServicesModule), +MODULE(nsProfileModule), +MODULE(Session_History_Module), +MODULE(application), +MODULE(nsCookieModule), +MODULE(nsXMLExtrasModule), +MODULE(nsUniversalCharDetModule), +MODULE(BOOT), +MODULE(NSS), #line 60 "nsStaticComponents.cpp.in" }; diff --git a/camino/src/bookmarks/BookmarksDataSource.mm b/camino/src/bookmarks/BookmarksDataSource.mm index de6cf71b6ac..7d2eaa84935 100644 --- a/camino/src/bookmarks/BookmarksDataSource.mm +++ b/camino/src/bookmarks/BookmarksDataSource.mm @@ -601,7 +601,7 @@ const int kBookmarksRootItemTag = -2; //Set cell's textual contents //[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString: nameAttr]]; - cellValue = [[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]]; + cellValue = [[[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]] autorelease]; //Create an attributed string to hold the empty attachment, then release the components. NSMutableAttributedString* attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; diff --git a/camino/src/browser/BrowserTabView.mm b/camino/src/browser/BrowserTabView.mm index f215b134dbe..a40bfd8ce33 100644 --- a/camino/src/browser/BrowserTabView.mm +++ b/camino/src/browser/BrowserTabView.mm @@ -100,6 +100,7 @@ - (BOOL)isOpaque { + // see http://developer.apple.com/qa/qa2001/qa1117.html if ( ([self tabViewType] == NSNoTabsBezelBorder) && (NSAppKitVersionNumber < 633) ) return NO; diff --git a/camino/src/browser/BrowserWindow.mm b/camino/src/browser/BrowserWindow.mm index 68592f4ae3a..faf2ff36dc8 100644 --- a/camino/src/browser/BrowserWindow.mm +++ b/camino/src/browser/BrowserWindow.mm @@ -54,6 +54,8 @@ static const int kEscapeKeyCode = 53; BOOL madeFirstResponder = [super makeFirstResponder:responder]; if (madeFirstResponder && oldResponder != [self firstResponder]) [(BrowserWindowController*)[self delegate] focusChangedFrom:oldResponder to:[self firstResponder]]; + + //NSLog(@"Old FR %@, new FR %@, responder %@, made %d", oldResponder, [self firstResponder], responder, madeFirstResponder); return madeFirstResponder; } diff --git a/camino/src/browser/BrowserWindowController.h b/camino/src/browser/BrowserWindowController.h index eb6789343dd..063a881b02a 100644 --- a/camino/src/browser/BrowserWindowController.h +++ b/camino/src/browser/BrowserWindowController.h @@ -109,12 +109,12 @@ typedef enum IBOutlet NSTextField* mLocationSheetURLField; IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock IBOutlet PageProxyIcon* mProxyIcon; - IBOutlet BrowserContentView* mContentView; + IBOutlet BrowserContentView* mContentView; IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource; - IBOutlet HistoryDataSource* mHistoryDataSource; + IBOutlet HistoryDataSource* mHistoryDataSource; - IBOutlet BookmarksToolbar* mPersonalToolbar; + IBOutlet BookmarksToolbar* mPersonalToolbar; IBOutlet NSWindow* mAddBookmarkSheetWindow; IBOutlet NSTextField* mAddBookmarkTitleField; @@ -191,6 +191,8 @@ typedef enum - (void)updateLocationFields:(NSString *)locationString; - (void)updateSiteIcons:(NSImage *)siteIconImage; - (void)updateToolbarItems; +- (void)loadingStarted; +- (void)loadingDone; - (void)focusURLBar; // call to update the image of the lock icon with a value from nsIWebProgressListener @@ -211,9 +213,9 @@ typedef enum - (IBAction)viewSource:(id)aSender; // focussed frame or page - (IBAction)viewPageSource:(id)aSender; // top-level page -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList; -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView; +- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; + - (IBAction)printDocument:(id)aSender; - (IBAction)pageSetup:(id)aSender; - (IBAction)performSearch:(id)aSender; @@ -302,6 +304,7 @@ typedef enum - (IBAction)bookmarkLink: (id)aSender; - (IBAction)copyLinkLocation:(id)aSender; +- (IBAction)copyImage:(id)sender; - (IBAction)copyImageLocation:(id)sender; - (BookmarksToolbar*) bookmarksToolbar; diff --git a/camino/src/browser/BrowserWindowController.mm b/camino/src/browser/BrowserWindowController.mm index 979a03ef020..c36add4099a 100644 --- a/camino/src/browser/BrowserWindowController.mm +++ b/camino/src/browser/BrowserWindowController.mm @@ -816,6 +816,19 @@ static NSArray* sToolbarDefaults = nil; else return YES; } + +- (void)loadingStarted +{ + [self updateToolbarItems]; + [self startThrobber]; +} + +- (void)loadingDone +{ + [self updateToolbarItems]; + [self stopThrobber]; + [mHistoryDataSource refresh]; +} - (void)updateToolbarItems { @@ -960,16 +973,14 @@ static NSArray* sToolbarDefaults = nil; } } -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView { - [[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView filterList:aFilterList]; + [[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView]; } -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename +- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename { - [[mBrowserView getBrowserView] saveURL: aFilterView filterList: aFilterList - url: aURLSpec suggestedFilename: aFilename]; + [[mBrowserView getBrowserView] saveURL: aFilterView url: aURLSpec suggestedFilename: aFilename]; } - (void)loadSourceOfURL:(NSString*)urlStr @@ -1890,12 +1901,14 @@ static NSArray* sToolbarDefaults = nil; - (IBAction)savePageAs:(id)aSender { - [self saveDocument:NO filterView:nil filterList: nil]; + NSView* accessoryView = [[NSApp delegate] getSavePanelView]; + [self saveDocument:NO filterView:accessoryView]; } - (IBAction)saveFrameAs:(id)aSender { - [self saveDocument:YES filterView:nil filterList: nil]; + NSView* accessoryView = [[NSApp delegate] getSavePanelView]; + [self saveDocument:YES filterView:accessoryView]; } - (IBAction)saveLinkAs:(id)aSender @@ -1915,8 +1928,7 @@ static NSArray* sToolbarDefaults = nil; nsAutoString text; GeckoUtils::GatherTextUnder(mContextMenuNode, text); - [self saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; + [self saveURL:nil url:hrefStr suggestedFilename:[NSString stringWith_nsAString:text]]; } - (IBAction)saveImageAs:(id)aSender @@ -1931,11 +1943,18 @@ static NSArray* sToolbarDefaults = nil; NSString* hrefStr = [NSString stringWith_nsAString: url]; - [self saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; + [self saveURL:nil url:hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; } } +- (IBAction)copyImage:(id)sender +{ + nsCOMPtr webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]); + nsCOMPtr clipboard(do_GetInterface(webBrowser)); + if (clipboard) + clipboard->CopyImageContents(); +} + - (IBAction)copyImageLocation:(id)sender { nsCOMPtr webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]); diff --git a/camino/src/browser/BrowserWrapper.mm b/camino/src/browser/BrowserWrapper.mm index c39050967c8..3f1a6120bc2 100644 --- a/camino/src/browser/BrowserWrapper.mm +++ b/camino/src/browser/BrowserWrapper.mm @@ -335,10 +335,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged"; mTabTitle = [mLoadingStatusString retain]; [mTabItem setLabel:mTabTitle]; - if (mWindowController) { - [mWindowController updateToolbarItems]; - [mWindowController startThrobber]; - } + if (mWindowController) + [mWindowController loadingStarted]; } - (void)onLoadingCompleted:(BOOL)succeeded @@ -402,10 +400,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged"; [self removeFromSuperview]; } - if (mWindowController) { - [mWindowController updateToolbarItems]; - [mWindowController stopThrobber]; - } + if (mWindowController) + [mWindowController loadingDone]; } - (void)onProgressChange:(int)currentBytes outOf:(int)maxBytes diff --git a/camino/src/browser/ContentClickListener.mm b/camino/src/browser/ContentClickListener.mm index bb18dd8fd91..57d8940282a 100644 --- a/camino/src/browser/ContentClickListener.mm +++ b/camino/src/browser/ContentClickListener.mm @@ -139,8 +139,7 @@ ContentClickListener::MouseClick(nsIDOMEvent* aEvent) nsAutoString text; GeckoUtils::GatherTextUnder(content, text); - [mBrowserController saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; + [mBrowserController saveURL:nil url:hrefStr suggestedFilename:[NSString stringWith_nsAString:text]]; } return NS_OK; diff --git a/camino/src/browser/KeychainService.h b/camino/src/browser/KeychainService.h index 3eeb9018fa1..2a167d7357a 100644 --- a/camino/src/browser/KeychainService.h +++ b/camino/src/browser/KeychainService.h @@ -51,10 +51,16 @@ class nsIPrefBranch; +enum KeychainPromptResult { kSave, kDontRemember, kNeverRemember } ; + @class CHBrowserView; + @interface KeychainService : NSObject { + IBOutlet id confirmStorePasswordPanel; + IBOutlet id confirmChangePasswordPanel; + BOOL mIsEnabled; BOOL mIsAutoFillEnabled; @@ -64,6 +70,13 @@ class nsIPrefBranch; + (KeychainService*) instance; - (void) shutdown:(id)sender; +- (IBAction)hitButtonOK:(id)sender; +- (IBAction)hitButtonCancel:(id)sender; +- (IBAction)hitButtonOther:(id)sender; + +- (KeychainPromptResult)confirmStorePassword:(NSWindow*)parent; +- (BOOL)confirmChangedPassword:(NSWindow*)parent; + - (BOOL) getUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSMutableString*)username password:(NSMutableString*)pwd item:(KCItemRef*)outItem; - (BOOL) findUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort; - (void) storeUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSString*)username password:(NSString*)pwd; @@ -75,13 +88,43 @@ class nsIPrefBranch; - (BOOL) isEnabled; - (BOOL) isAutoFillEnabled; +// routines to manipulate the keychain deny list for which hosts we shouldn't +// ask about +- (void) addHostToDenyList:(NSString*)host; +- (BOOL) isHostInDenyList:(NSString*)host; + @end + +// +// KeychainDenyList +// +// A singleton object that maintains a list of sites where we should +// not prompt the user for saving in the keychain. This object also +// handles archiving the list in the user's profile dir. +// + +@interface KeychainDenyList : NSObject +{ + NSMutableArray* mDenyList; // the list + BOOL mIsDirty; // do we need to write the list to disk? +} + ++ (KeychainDenyList*) instance; +- (void) shutdown:(id)sender; + +- (BOOL) isHostPresent:(NSString*)host; +- (void) addHost:(NSString*)host; +- (void) removeHost:(NSString*)host; +- (void) writeToDisk; + +@end + + class KeychainPrompt : public nsIAuthPromptWrapper { public: KeychainPrompt(); - KeychainPrompt(KeychainService*); virtual ~KeychainPrompt(); NS_DECL_ISUPPORTS @@ -95,7 +138,6 @@ protected: static void ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost, PRInt32* outPort); nsCOMPtr mPrompt; - KeychainService* mKeychain; }; // @@ -105,7 +147,7 @@ class KeychainFormSubmitObserver : public nsIObserver, public nsIFormSubmitObserver { public: - KeychainFormSubmitObserver(KeychainService*); + KeychainFormSubmitObserver(); virtual ~KeychainFormSubmitObserver(); NS_DECL_ISUPPORTS @@ -116,12 +158,10 @@ public: private: - static BOOL CheckStorePasswordYN(nsIDOMWindowInternal*); + static KeychainPromptResult CheckStorePasswordYN(nsIDOMWindowInternal*); static BOOL CheckChangeDataYN(nsIDOMWindowInternal*); static NSWindow* GetNSWindow(nsIDOMWindowInternal* inWindow); - - KeychainService* mKeychain; }; // @@ -129,11 +169,10 @@ private: // @interface KeychainBrowserListener : NSObject { - KeychainService* mKeychain; CHBrowserView* mBrowserView; } -- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser; +- (id)initWithBrowser:(CHBrowserView*)aBrowser; @end diff --git a/camino/src/browser/KeychainService.mm b/camino/src/browser/KeychainService.mm index c20a16db4c8..94f514531c6 100644 --- a/camino/src/browser/KeychainService.mm +++ b/camino/src/browser/KeychainService.mm @@ -69,6 +69,9 @@ #include "nsIWindowWatcher.h" #include "nsIWebBrowserChrome.h" #include "nsIEmbeddingSiteWindow.h" +#include "nsAppDirectoryServiceDefs.h" + +extern NSString* XPCOMShutDownNotificationName; nsresult @@ -114,7 +117,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // observer service uses a weakref. nsCOMPtr svc = do_GetService("@mozilla.org/observer-service;1"); NS_ASSERTION(svc, "Keychain can't get observer service"); - mFormSubmitObserver = new KeychainFormSubmitObserver(self); + mFormSubmitObserver = new KeychainFormSubmitObserver(); if ( mFormSubmitObserver && svc ) { NS_ADDREF(mFormSubmitObserver); svc->AddObserver(mFormSubmitObserver, NS_FORMSUBMIT_SUBJECT, PR_FALSE); @@ -122,7 +125,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // register for the cocoa notification posted when XPCOM shutdown so we // can unregister the pref callbacks we register below - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:@"XPCOM Shutdown" + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName object:nil]; // cache the values of the prefs and register pref-changed callbacks. Yeah, I know @@ -139,6 +142,10 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) pref->RegisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull); } } + + // load the keychain.nib file with our dialogs in it + BOOL success = [NSBundle loadNibNamed:@"Keychain" owner:self]; + NS_ASSERTION(success, "can't load keychain prompt dialogs"); } return self; } @@ -168,6 +175,8 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) pref->UnregisterCallback(gUseKeychainPref, KeychainPrefChangedCallback, nsnull); pref->UnregisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull); } + + [sInstance release]; } @@ -324,7 +333,181 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // - (void) addListenerToView:(CHBrowserView*)view { - [view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:self browser:view] autorelease]]; + [view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:view] autorelease]]; +} + +// +// hitButtonOK: +// hitButtonCancel: +// hitButtonOther: +// +// actions for the buttons of the keychain prompt dialogs. +// + +enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 }; + +- (IBAction)hitButtonOK:(id)sender +{ + [NSApp stopModalWithCode:kOKButton]; +} + +- (IBAction)hitButtonCancel:(id)sender +{ + [NSApp stopModalWithCode:kCancelButton]; +} + +- (IBAction)hitButtonOther:(id)sender +{ + [NSApp stopModalWithCode:kOtherButton]; +} + +// +// confirmStorePassword: +// +// Puts up a dialog when the keychain doesn't yet have an entry from +// this site asking to store it, forget it this once, or mark the site +// on a deny list so we never ask again. +// +- (KeychainPromptResult)confirmStorePassword:(NSWindow*)parent +{ + int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent]; + [confirmStorePasswordPanel close]; + + // the results of hitButtonXX: map to the corresponding values in the + // |KeychainPromptResult| enum so we can just cast and return + return NS_STATIC_CAST(KeychainPromptResult, result); +} + +// +// confirmChangedPassword: +// +// The password stored in the keychain differs from what the user typed +// in. Ask what they want to do to resolve the issue. +// +- (BOOL)confirmChangedPassword:(NSWindow*)parent +{ + int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent]; + [confirmChangePasswordPanel close]; + return (result == kOKButton); +} + + +- (void) addHostToDenyList:(NSString*)host +{ + [[KeychainDenyList instance] addHost:host]; +} + +- (BOOL) isHostInDenyList:(NSString*)host +{ + return [[KeychainDenyList instance] isHostPresent:host]; +} + +@end + + +@interface KeychainDenyList (KeychainDenyListPrivate) +- (NSString*) pathToDenyListFile; +@end + + +@implementation KeychainDenyList + +static KeychainDenyList *sDenyListInstance = nil; + ++ (KeychainDenyList*) instance +{ + return sDenyListInstance ? sDenyListInstance : sDenyListInstance = [[self alloc] init]; +} + +- (id) init +{ + if ( (self = [super init]) ) { + mDenyList = [[NSUnarchiver unarchiveObjectWithFile:[self pathToDenyListFile]] retain]; + if ( !mDenyList ) + mDenyList = [[NSMutableArray alloc] init]; + + mIsDirty = NO; + + // register for the cocoa notification posted when XPCOM shutdown so we + // can release our singleton and flush the file + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName object:nil]; + } + return self; +} + +- (void) dealloc +{ + [self writeToDisk]; + [mDenyList release]; +} + +// +// shutdown: +// +// Called in response to the cocoa notification "XPCOM Shutdown" sent by the cocoa +// browser service before it terminates embedding and shuts down xpcom. Allows us +// to get rid of anything we're holding onto for the length of the app. +// +- (void) shutdown:(id)unused +{ + [sDenyListInstance release]; +} + +// +// writeToDisk +// +// flushes the deny list to the save file in the user's profile, but only +// if it has changed since we read it in. +// +- (void) writeToDisk +{ + if ( mIsDirty ) + [NSArchiver archiveRootObject:mDenyList toFile:[self pathToDenyListFile]]; + mIsDirty = NO; +} + +- (BOOL) isHostPresent:(NSString*)host +{ + return [mDenyList containsObject:host]; +} + +- (void) addHost:(NSString*)host +{ + if ( ![self isHostPresent:host] ) { + [mDenyList addObject:host]; + mIsDirty = YES; + } +} + +- (void) removeHost:(NSString*)host +{ + if ( [self isHostPresent:host] ) { + [mDenyList removeObject:host]; + mIsDirty = YES; + } +} + + +// +// pathToDenyListFile +// +// returns a path ('/' delimited) that cocoa can use to point to the +// deny list save file in the current user's profile +// +- (NSString*) pathToDenyListFile +{ + NSMutableString* path = [[[NSMutableString alloc] init] autorelease]; + + nsCOMPtr appProfileDir; + NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(appProfileDir)); + if ( appProfileDir ) { + nsAutoString profilePath; + appProfileDir->GetPath(profilePath); + [path setString:[NSString stringWith_nsAString:profilePath]]; + [path appendString:@"/Keychain Deny List"]; // |profilePath| is '/' delimited + } + + return path; } @end @@ -338,12 +521,6 @@ NS_IMPL_ISUPPORTS2(KeychainPrompt, nsIAuthPromptWrapper) KeychainPrompt::KeychainPrompt() - : mKeychain([KeychainService instance]) -{ - NS_INIT_ISUPPORTS(); -} - -KeychainPrompt::KeychainPrompt(KeychainService* keychain) : mKeychain(keychain) { NS_INIT_ISUPPORTS(); } @@ -391,7 +568,8 @@ KeychainPrompt::ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost, void KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pwd) { - if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled]) + KeychainService* keychain = [KeychainService instance]; + if(![keychain isEnabled] || ![keychain isAutoFillEnabled]) return; NSString* host = nil; @@ -409,7 +587,7 @@ KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pw // Pre-fill user/password if found in the keychain. // KCItemRef ignore; - if([mKeychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) { + if([keychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) { if ( user ) *user = [username createNewUnicodeBuffer]; if ( pwd ) @@ -427,10 +605,12 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u NSString* username = [NSString stringWithPRUnichars:user]; NSString* password = [NSString stringWithPRUnichars:pwd]; + KeychainService* keychain = [KeychainService instance]; + NSMutableString* origUsername = [NSMutableString string]; NSMutableString* origPwd = [NSMutableString string]; KCItemRef itemRef; - bool found = [mKeychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef]; + bool found = [keychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef]; // // Update, store or remove the user/password depending on the user @@ -438,11 +618,11 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u // keychain. // if(checked && !found) - [mKeychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password]; + [keychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password]; else if(checked && found && (![origUsername isEqualToString:username] || ![origPwd isEqualToString:password])) - [mKeychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef]; + [keychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef]; else if(!checked && found) - [mKeychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef]; + [keychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef]; } // @@ -476,7 +656,7 @@ KeychainPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle, { PreFill(realm, user, pwd); - PRBool checked = [mKeychain isEnabled]; + PRBool checked = [[KeychainService instance] isEnabled]; PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer]; nsresult rv = mPrompt->PromptUsernameAndPassword(dialogTitle, text, user, pwd, checkTitle, &checked, _retval); @@ -501,7 +681,7 @@ KeychainPrompt::PromptPassword(const PRUnichar *dialogTitle, { PreFill(realm, nsnull, pwd); - PRBool checked = [mKeychain isEnabled]; + PRBool checked = [[KeychainService instance] isEnabled]; PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer]; nsresult rv = mPrompt->PromptPassword(dialogTitle, text, pwd, checkTitle, &checked, _retval); @@ -530,7 +710,7 @@ NS_IMPL_ISUPPORTS2(KeychainFormSubmitObserver, nsIObserver, nsIFormSubmitObserver) -KeychainFormSubmitObserver::KeychainFormSubmitObserver(KeychainService* keychain) : mKeychain(keychain) +KeychainFormSubmitObserver::KeychainFormSubmitObserver() { NS_INIT_ISUPPORTS(); //NSLog(@"Keychain form submit observer created."); @@ -551,7 +731,8 @@ NS_IMETHODIMP KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* window, nsIURI* actionURL, PRBool* cancelSubmit) { - if (![mKeychain isEnabled]) + KeychainService* keychain = [KeychainService instance]; + if (![keychain isEnabled]) return NS_OK; nsCOMPtr formNode(do_QueryInterface(node)); @@ -590,25 +771,41 @@ KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* windo docURL->GetHost(host); docURL->GetPort(&port); + // is the host in the deny list? if yes, bail. otherwise check the keychain. + NSString* realm = [NSString stringWithCString:host.get()]; + if ( [keychain isHostInDenyList:realm] ) + return NS_OK; + // // If there's already an entry in the keychain, check if the username // and password match. If not, ask the user what they want to do and replace // it as necessary. If there's no entry, ask if they want to remember it // and then put it into the keychain // - NSString* realm = [NSString stringWithCString:host.get()]; NSString* existingUser = [NSMutableString string]; NSString* existingPassword = [NSMutableString string]; KCItemRef itemRef; - BOOL foundExistingPassword = [mKeychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef]; + BOOL foundExistingPassword = [keychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef]; if ( foundExistingPassword ) { if ( !([existingUser isEqualToString:username] && [existingPassword isEqualToString:password]) ) if ( CheckChangeDataYN(window) ) - [mKeychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef]; + [keychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef]; } else { - if (CheckStorePasswordYN(window)) - [mKeychain storeUsernameAndPassword:realm port:port user:username password:password]; + switch (CheckStorePasswordYN(window)) { + case kSave: + [keychain storeUsernameAndPassword:realm port:port user:username password:password]; + break; + + case kNeverRemember: + // tell the keychain we never want to be prompted about this host again + [keychain addHostToDenyList:realm]; + break; + + case kDontRemember: + // do nothing at all + break; + } } } @@ -644,12 +841,11 @@ KeychainFormSubmitObserver::GetNSWindow(nsIDOMWindowInternal* inWindow) return nswindow; } -BOOL +KeychainPromptResult KeychainFormSubmitObserver::CheckStorePasswordYN(nsIDOMWindowInternal* window) { NSWindow* nswindow = GetNSWindow(window); - nsAlertController* dialog = CHBrowserService::GetAlertController(); - return [dialog confirmStorePassword:nswindow]; + return [[KeychainService instance] confirmStorePassword:nswindow]; } @@ -657,16 +853,14 @@ BOOL KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) { NSWindow* nswindow = GetNSWindow(window); - nsAlertController* dialog = CHBrowserService::GetAlertController(); - return [dialog confirmChangedPassword:nswindow]; + return [[KeychainService instance] confirmChangedPassword:nswindow]; } @implementation KeychainBrowserListener -- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser +- (id)initWithBrowser:(CHBrowserView*)aBrowser { if ( (self = [super init]) ) { - mKeychain = keychain; mBrowserView = aBrowser; } return self; @@ -683,7 +877,8 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) if(!succeeded) return; - if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled]) + KeychainService* keychain = [KeychainService instance]; + if(![keychain isEnabled] || ![keychain isAutoFillEnabled]) return; nsCOMPtr domWin = getter_AddRefs([mBrowserView getContentWindow]); @@ -750,7 +945,7 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) docURL->GetPort(&port); KCItemRef ignore; - if ([mKeychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) { + if ([keychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) { nsAutoString user, pwd; [username assignTo_nsAString:user]; [password assignTo_nsAString:pwd]; diff --git a/camino/src/browser/SiteIconProvider.mm b/camino/src/browser/SiteIconProvider.mm index e6c1709218e..3cf26d6414c 100644 --- a/camino/src/browser/SiteIconProvider.mm +++ b/camino/src/browser/SiteIconProvider.mm @@ -286,7 +286,7 @@ static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& o NSImage* faviconImage = nil; NS_DURING - faviconImage = [[NSImage alloc] initWithData:data]; + faviconImage = [[[NSImage alloc] initWithData:data] autorelease]; NS_HANDLER NSLog(@"Exception \"%@ making\" favicon image for %@", localException, inURI); faviconImage = nil; diff --git a/camino/src/browser/nsAlertController.h b/camino/src/browser/nsAlertController.h index 1790fc2054d..91bdc274498 100644 --- a/camino/src/browser/nsAlertController.h +++ b/camino/src/browser/nsAlertController.h @@ -53,8 +53,6 @@ IBOutlet id confirmPanelText; IBOutlet id confirmPanelButton1; IBOutlet id confirmPanelButton2; - IBOutlet id confirmStorePasswordPanel; - IBOutlet id confirmChangePasswordPanel; IBOutlet id promptPanel; IBOutlet id promptPanelCheck; IBOutlet id promptPanelText; @@ -90,8 +88,6 @@ - (int)confirmCheckEx:(NSWindow*)parent title:(NSString*)title text:(NSString*)text button1:(NSString*)btn1 button2:(NSString*)btn2 button3:(NSString*)btn3 checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue; -- (BOOL)confirmStorePassword:(NSWindow*)parent; -- (BOOL)confirmChangedPassword:(NSWindow*)parent; - (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck; - (BOOL)promptUserNameAndPassword:(NSWindow*)parent title:(NSString*)title text:(NSString*)text userNameText:(NSMutableString*)userNameText passwordText:(NSMutableString*)passwordText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck; diff --git a/camino/src/browser/nsAlertController.mm b/camino/src/browser/nsAlertController.mm index 8f1ac58cd80..326878cc28d 100644 --- a/camino/src/browser/nsAlertController.mm +++ b/camino/src/browser/nsAlertController.mm @@ -154,19 +154,6 @@ enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 }; return result; } -- (BOOL)confirmStorePassword:(NSWindow*)parent -{ - int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent]; - [confirmStorePasswordPanel close]; - return (result == kOKButton); -} - -- (BOOL)confirmChangedPassword:(NSWindow*)parent -{ - int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent]; - [confirmChangePasswordPanel close]; - return (result == kOKButton); -} - (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck { diff --git a/camino/src/download/ProgressDlgController.h b/camino/src/download/ProgressDlgController.h index 3b1b3a3a861..93496b25ab4 100644 --- a/camino/src/download/ProgressDlgController.h +++ b/camino/src/download/ProgressDlgController.h @@ -20,6 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Simon Fraser + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -38,49 +40,72 @@ #import #import "CHDownloadProgressDisplay.h" +#import "CHStackView.h" -#include "nscore.h" +/* + How ProgressViewController and ProgressDlgController work. + + ProgressDlgController manages the window the the downloads are displayed in. + It contains a single CHStackView, a custom class that asks its datasource + for a list of views to display, in a similar fashion to the way NSTableView + asks its datasource for data to display. There is a single instance of + ProgressDlgController, returned by +sharedDownloadController. + + The ProgressDlgController is a subclass of CHDownloadController, which + means that it gets asked to create new objects conforming to the + CHDownloadProgressDisplay protocol, which are used to display + the progress of a single download. It does so by returning instances of + ProgressViewController, which manage an NSView that contains a progress + indicator, some text fields for status info and a cancel button. + + After a ProgressViewController is requested, the CHStackView is reloaded, + which causes it to ask the ProgressDlgController (it's datasource) to + provide it with a list of all the subviews to be diaplyed. It calculates + it's new frame, and arranges the subviews in a vertical list. + + The ProgressDlgController now needs to resize its window. It knows when + to do this because is watches for changes in the CHStackViews frame (using + NSViews built in NSNotification for this). + + + Expanding/contracting download progress views + + When a disclosure triangle is clicked, the ProgressViewController just swaps + the expanded view for a smaller one. It saves the new state as the users + preference for "browser.download.compactView". If the option key was held down, + a notification is posted (that all ProgressViewControllers listen for) that + makes all ProgressViewControllers change their state to the new state of the sender. -class nsIWebBrowserPersist; -class nsISupports; -class nsIInputStream; -class nsDownloadListener; +*/ +#import "CHDownloadProgressDisplay.h" -@interface ChimeraDownloadControllerFactory : DownloadControllerFactory -@end - - -@interface ProgressDlgController : NSWindowController +@interface ProgressDlgController : NSWindowController { - IBOutlet NSTextField *mElapsedTimeLabel; - IBOutlet NSTextField *mFromField; - IBOutlet NSTextField *mStatusLabel; - IBOutlet NSTextField *mTimeLeftLabel; - IBOutlet NSTextField *mToField; - IBOutlet NSProgressIndicator *mProgressBar; - - NSToolbarItem *leaveOpenToggleToolbarItem; - - BOOL mSaveFileDialogShouldStayOpen; - BOOL mDoingAutoFileDownload; - BOOL mIsFileSave; - BOOL mDownloadIsComplete; - long mCurrentProgress; // if progress bar is indeterminate, can still calc stats. - - CHDownloader *mDownloader; // we hold a ref to this - NSTimer *mDownloadTimer; + IBOutlet CHStackView *mStackView; + IBOutlet NSScrollView *mScrollView; + IBOutlet NSTextField *mNoDownloadsText; + + NSSize mDefaultWindowSize; + NSTimer *mDownloadTimer; + NSMutableArray *mProgressViewControllers; + int mNumActiveDownloads; } -+ (int)numDownloadInProgress; ++ (ProgressDlgController *)sharedDownloadController; --(void)autosaveWindowFrame; +- (int)numDownloadsInProgress; --(void) setupDownloadTimer; --(void) killDownloadTimer; --(void) setDownloadProgress:(NSTimer *)aTimer; --(NSString *) formatTime:(int)aSeconds; --(NSString *) formatFuzzyTime:(int)aSeconds; --(NSString *) formatBytes:(float)aBytes; +- (void)autosaveWindowFrame; + +- (void)setupDownloadTimer; +- (void)killDownloadTimer; +- (void)setDownloadProgress:(NSTimer *)aTimer; + +- (void)didStartDownload:(id )progressDisplay; +- (void)didEndDownload:(id )progressDisplay; +- (void)removeDownload:(id )progressDisplay; + +- (NSApplicationTerminateReply)allowTerminate; @end diff --git a/camino/src/download/ProgressDlgController.mm b/camino/src/download/ProgressDlgController.mm index f602e492d4c..9ce24f3576a 100644 --- a/camino/src/download/ProgressDlgController.mm +++ b/camino/src/download/ProgressDlgController.mm @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,504 +36,319 @@ * * ***** END LICENSE BLOCK ***** */ +#import "NSView+Utils.h" + #import "ProgressDlgController.h" -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsCRT.h" -#include "nsIWebBrowserPersist.h" -#include "nsIInputStream.h" -#include "nsIURL.h" -#include "nsILocalFile.h" -#include "nsIDOMHTMLDocument.h" -#include "nsIWebProgressListener.h" -#include "nsIDownload.h" -#include "nsIComponentManager.h" -#include "nsIPref.h" - -static NSString *SaveFileToolbarIdentifier = @"Save File Dialog Toolbar"; -static NSString *CancelToolbarItemIdentifier = @"Cancel Toolbar Item"; -static NSString *ShowFileToolbarItemIdentifier = @"Show File Toolbar Item"; -static NSString *OpenFileToolbarItemIdentifier = @"Open File Toolbar Item"; -static NSString *LeaveOpenToolbarItemIdentifier = @"Leave Open Toggle Toolbar Item"; +#import "ProgressViewController.h" +#import "PreferenceManager.h" static NSString *ProgressWindowFrameSaveName = @"ProgressWindow"; -@implementation ChimeraDownloadControllerFactory : DownloadControllerFactory -- (NSWindowController *)createDownloadController -{ - NSWindowController* progressController = [[ProgressDlgController alloc] initWithWindowNibName: @"ProgressDialog"]; - NSAssert([progressController conformsToProtocol:@protocol(CHDownloadProgressDisplay)], - @"progressController should conform to CHDownloadProgressDisplay protocol"); - return progressController; -} + +@interface ProgressDlgController(PrivateProgressDlgController) + +- (void)resizeWindowToFit; +- (void)rebuildViews; +- (NSSize)windowSizeForStackSize:(NSSize)stackSize; @end -#pragma mark - -@interface ProgressDlgController(Private) --(void)setupToolbar; -@end - @implementation ProgressDlgController -static int gNumActiveDownloads = 0; +static id gSharedProgressController = nil; -+ (int)numDownloadInProgress ++ (ProgressDlgController *)sharedDownloadController; { - return gNumActiveDownloads; + if (gSharedProgressController == nil) + gSharedProgressController = [[ProgressDlgController alloc] init]; + + return gSharedProgressController; +} + +- (id)init +{ + if ((self == [super initWithWindowNibName:@"ProgressDialog"])) + { + // Register for notifications when the stack view changes size + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stackViewResized:) + name:StackViewResizedNotificationName + object:nil]; + + mProgressViewControllers = [[NSMutableArray alloc] init]; + + mDefaultWindowSize = [[self window] frame].size; + // it would be nice if we could get the frame from the name, and then + // mess with it before setting it. + [[self window] setFrameUsingName:ProgressWindowFrameSaveName]; + // set the window to its default height + NSRect windowFrame = [[self window] frame]; + windowFrame.size.height = mDefaultWindowSize.height; + [[self window] setFrame:windowFrame display:NO]; + + // We provide the views for the stack view, from mProgressViewControllers + [mStackView setDataSource:self]; + + [mScrollView setDrawsBackground:NO]; + [mNoDownloadsText retain]; // so we can remove it from its superview + } + + return self; } - (void)dealloc { - // if we get here because we're quitting, the listener will still be alive - // yet we're going away. As a result, we need to tell the d/l listener to - // forget it ever met us and necko will clean it up on its own. - if ( mDownloader) - mDownloader->DetachDownloadDisplay(); - NS_IF_RELEASE(mDownloader); + if (self == gSharedProgressController) + gSharedProgressController = nil; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [mProgressViewControllers release]; + [mNoDownloadsText release]; + [self killDownloadTimer]; [super dealloc]; } -- (void)windowDidLoad +- (void)didStartDownload:(id )progressDisplay { - [super windowDidLoad]; - - mDownloadIsComplete = NO; - mDoingAutoFileDownload = NO; + [self showWindow:nil]; // make sure the window is visible - if (!mIsFileSave) { - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - PRBool save = PR_FALSE; - prefs->GetBoolPref("browser.download.progressDnldDialog.keepAlive", &save); - mSaveFileDialogShouldStayOpen = save; - - PRBool autoHelperDispatch = PR_FALSE; - prefs->GetBoolPref("browser.download.autoDispatch", &autoHelperDispatch); - mDoingAutoFileDownload = autoHelperDispatch; + [self rebuildViews]; + [self setupDownloadTimer]; +} + +- (void)didEndDownload:(id )progressDisplay +{ + [self rebuildViews]; // to swap in the completed view +} + +- (void)removeDownload:(id )progressDisplay +{ + [mProgressViewControllers removeObject:progressDisplay]; + + if ([mProgressViewControllers count] == 0) + { + // Stop doing stuff if there aren't any downloads going on + [self killDownloadTimer]; } - [self setupToolbar]; - [mProgressBar setUsesThreadedAnimation:YES]; - [mProgressBar startAnimation:self]; // move to onStateChange + [self rebuildViews]; } -- (void)setupToolbar +- (void)stackViewResized:(NSNotification *)notification { - NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:SaveFileToolbarIdentifier] autorelease]; - - [toolbar setDisplayMode:NSToolbarDisplayModeDefault]; - [toolbar setAllowsUserCustomization:YES]; - [toolbar setAutosavesConfiguration:YES]; - [toolbar setDelegate:self]; - [[self window] setToolbar:toolbar]; + NSDictionary* userInfo = [notification userInfo]; + NSSize oldStackSize = [[userInfo objectForKey:@"oldsize"] sizeValue]; + + // this code is used to auto-resize the downloads window when + // its contents change size, if the window is in its standard, "zoomed" + // state. This allows the user to choose between auto-resizing behavior, + // by leaving the window alone, or their own size, by resizing it. + + // get the size the window would have been if it had been in the + // standard state, given the old size of the contents + NSSize oldZoomedWindowSize = [self windowSizeForStackSize:oldStackSize]; + NSSize curWindowSize = [[self window] frame].size; + + // only resize if the window matches the stack size + if (CHCloseSizes(oldZoomedWindowSize, curWindowSize, 4.0)) + [self resizeWindowToFit]; } -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar +// given the dimensions of our stack view, return the dimensions of the window, +// assuming the window is zoomed to show as much of the contents as possible. +- (NSSize)windowSizeForStackSize:(NSSize)stackSize { - return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, - ShowFileToolbarItemIdentifier, - OpenFileToolbarItemIdentifier, - LeaveOpenToolbarItemIdentifier, - NSToolbarCustomizeToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - NSToolbarSpaceItemIdentifier, - NSToolbarSeparatorItemIdentifier, - nil]; + NSSize actualScrollFrame = [mScrollView frame].size; + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:stackSize + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; + + // frameSizeForContentSize seems to return a width 1 pixel too narrow + scrollFrameSize.width += 1; + + NSRect contentRect = [[[self window] contentView] frame]; + contentRect.size.width += scrollFrameSize.width - actualScrollFrame.width; + contentRect.size.height += scrollFrameSize.height - actualScrollFrame.height; + contentRect.origin = [[self window] convertBaseToScreen:contentRect.origin]; // convert to screen + + NSRect advisoryWindowFrame = [NSWindow frameRectForContentRect:contentRect styleMask:[[self window] styleMask]]; + NSRect constrainedRect = [[self window] constrainFrameRect:advisoryWindowFrame toScreen:[[self window] screen]]; + return constrainedRect.size; } -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar +- (void)resizeWindowToFit { - return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - LeaveOpenToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - ShowFileToolbarItemIdentifier, - OpenFileToolbarItemIdentifier, - nil]; + if ([mProgressViewControllers count] > 0) + { + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; + NSSize curScrollFrameSize = [mScrollView frame].size; + + NSRect windowFrame = [[self window] frame]; + + float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height); + windowFrame.size.height += frameDelta; + windowFrame.origin.y -= frameDelta; // maintain top + + [[self window] setFrame:windowFrame display:YES]; + } } -- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem +- (void)rebuildViews { - if ([toolbarItem action] == @selector(cancel)) // cancel button - return (!mDownloadIsComplete); - if ([toolbarItem action] == @selector(pauseAndResumeDownload)) // pause/resume button - return (NO); // Hey - it hasn't been hooked up yet. !mDownloadIsComplete when it is. - if ([toolbarItem action] == @selector(showFile)) // show file - return (mDownloadIsComplete); - if ([toolbarItem action] == @selector(openFile)) // open file - return (mDownloadIsComplete); - return YES; // turn it on otherwise. + [mStackView reloadSubviews]; + + if ([mProgressViewControllers count] == 0) + { + [[[self window] contentView] addSubview:mNoDownloadsText]; + } + else + { + [mNoDownloadsText removeFromSuperview]; + } + +} + +- (int)numDownloadsInProgress +{ + unsigned int numViews = [mProgressViewControllers count]; + int numActive = 0; + + for (unsigned int i = 0; i < numViews; i++) + { + if ([[mProgressViewControllers objectAtIndex:i] isActive]) + ++numActive; + } + return numActive; } -(void)autosaveWindowFrame { - [[self window] saveFrameUsingName: ProgressWindowFrameSaveName]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar - itemForItemIdentifier:(NSString *)itemIdent - willBeInsertedIntoToolbar:(BOOL)willBeInserted -{ - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease]; - - if ( [itemIdent isEqual:CancelToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Cancel",@"Cancel")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"CancelPaletteLabel",@"Cancel Download")]; - [toolbarItem setToolTip:NSLocalizedString(@"CancelToolTip",@"Cancel this file download")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveCancel"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(cancel)]; - } - else if ( [itemIdent isEqual:ShowFileToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Show File",@"Show File")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Show File",@"Show File")]; - [toolbarItem setToolTip:NSLocalizedString(@"ShowToolTip",@"Show the saved file in the Finder")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveShowFile"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(showFile)]; - } - else if ( [itemIdent isEqual:OpenFileToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Open File",@"Open File")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Open File",@"Open File")]; - [toolbarItem setToolTip:NSLocalizedString(@"OpenToolTip",@"Open the saved file in its default application.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveOpenFile"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(openFile)]; - } - else if ( [itemIdent isEqual:LeaveOpenToolbarItemIdentifier] ) - { - if ( !mIsFileSave && !mDoingAutoFileDownload ) - { - if ( mSaveFileDialogShouldStayOpen ) - { - [toolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [toolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(toggleLeaveOpen)]; - } - else - { - [toolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [toolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(toggleLeaveOpen)]; - } - if ( willBeInserted ) - { - leaveOpenToggleToolbarItem = toolbarItem; //establish reference - } - } - } else - { - toolbarItem = nil; - } - - return toolbarItem; -} - --(void)cancel -{ - if (mDownloader) // we should always have one - mDownloader->CancelDownload(); - - // clean up downloaded file. - do it here on in CancelDownload? - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *thePath = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([fileManager isDeletableFileAtPath:thePath]) - // if we delete it, fantastic. if not, oh well. better to move to trash instead? - [fileManager removeFileAtPath:thePath handler:nil]; - - // we can _not_ set the |mDownloadIsComplete| flag here because the download really - // isn't done yet. We'll probably continue to process more PLEvents that are already - // in the queue until we get a STATE_STOP state change. As a result, we just keep - // going until that comes in (and it will, because we called CancelDownload() above). - // Ensure that the window goes away when we get there by flipping the 'stay alive' - // flag. (bug 154913) - mSaveFileDialogShouldStayOpen = NO; -} - --(void)showFile -{ - NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([[NSWorkspace sharedWorkspace] selectFile:theFile - inFileViewerRootedAtPath:[theFile stringByDeletingLastPathComponent]]) - return; - // hmmm. it didn't work. that's odd. need localized error messages. for now, just beep. - NSBeep(); -} - --(void)openFile -{ - NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([[NSWorkspace sharedWorkspace] openFile:theFile]) - return; - // hmmm. it didn't work. that's odd. need localized error message. for now, just beep. - NSBeep(); - -} - --(void)toggleLeaveOpen -{ - if ( ! mSaveFileDialogShouldStayOpen ) { - mSaveFileDialogShouldStayOpen = YES; - [leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")]; - [leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")]; - [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; - } else { - mSaveFileDialogShouldStayOpen = NO; - [leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")]; - [leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")]; - [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; - } - - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - prefs->SetBoolPref("browser.download.progressDnldDialog.keepAlive", mSaveFileDialogShouldStayOpen); + [[self window] saveFrameUsingName:ProgressWindowFrameSaveName]; } - (void)windowWillClose:(NSNotification *)notification { [self autosaveWindowFrame]; - [self autorelease]; -} - -- (BOOL)windowShouldClose:(NSNotification *)notification -{ - [self killDownloadTimer]; - if (!mDownloadIsComplete) { //whoops. hard cancel. - [self cancel]; - return NO; // let setDownloadProgress handle the close. - } - return YES; } - (void)killDownloadTimer { - if (mDownloadTimer) { + if (mDownloadTimer) + { [mDownloadTimer invalidate]; [mDownloadTimer release]; mDownloadTimer = nil; - } + } } + - (void)setupDownloadTimer { [self killDownloadTimer]; - mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 - target:self - selector:@selector(setDownloadProgress:) - userInfo:nil - repeats:YES] retain]; -} - --(NSString *)formatTime:(int)seconds -{ - NSMutableString *theTime =[[[NSMutableString alloc] initWithCapacity:8] autorelease]; - [theTime setString:@""]; - NSString *padZero = [NSString stringWithString:@"0"]; - //write out new elapsed time - if (seconds >= 3600){ - [theTime appendFormat:@"%d:",(seconds / 3600)]; - seconds = seconds % 3600; - } - NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)]; - if ([elapsedMin length] == 2) - [theTime appendString:[padZero stringByAppendingString:elapsedMin]]; - else - [theTime appendString:elapsedMin]; - seconds = seconds % 60; - NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds]; - if ([elapsedSec length] == 2) - [theTime appendString:elapsedSec]; - else - [theTime appendString:[padZero stringByAppendingString:elapsedSec]]; - return theTime; -} -// fuzzy time gives back strings like "about 5 seconds" --(NSString *)formatFuzzyTime:(int)seconds -{ - // check for seconds first - if (seconds < 60) { - if (seconds < 7) - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),5] autorelease]; - if (seconds < 13) - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),10] autorelease]; - return [[[NSString alloc] initWithString:NSLocalizedString(@"UnderMin",@"Under a minute")] autorelease]; - } - // seconds becomes minutes and we keep checking. - seconds = seconds/60; - if (seconds < 60) { - if (seconds < 2) - return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutMin",@"About a minute")] autorelease]; - // OK, tell the good people how much time we have left. - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"),seconds] autorelease]; - } - //this download will never seemingly never end. now seconds become hours. - seconds = seconds/60; - if (seconds < 2) - return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutHour",@"Over an hour")] autorelease]; - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutHours",@"Over %d hours"),seconds] autorelease]; -} - - --(NSString *)formatBytes:(float)bytes -{ // this is simpler than my first try. I peaked at Omnigroup byte formatting code. - // if bytes are negative, we return question marks. - if (bytes < 0) - return [[[NSString alloc] initWithString:@"???"] autorelease]; - // bytes first. - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f bytes",bytes] autorelease]; - // kb - bytes = bytes/1024; - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f KB",bytes] autorelease]; - // mb - bytes = bytes/1024; - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f MB",bytes] autorelease]; - // gb - bytes = bytes/1024; - return [[[NSString alloc] initWithFormat:@"%.1f GB",bytes] autorelease]; -} - -// this handles lots of things. -- (void)setDownloadProgress:(NSTimer *)downloadTimer; -{ - // XXX this logic needs cleaning up. - // Ack! we're closing the window with the download still running! - if (mDownloadIsComplete) + mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 + target:self + selector:@selector(setDownloadProgress:) + userInfo:nil + repeats:YES] retain]; +} + +// Called by our timer to refresh all the download stats +- (void)setDownloadProgress:(NSTimer *)aTimer +{ + [mProgressViewControllers makeObjectsPerformSelector:@selector(refreshDownloadInfo)]; + // if the window is minimized, we want to update the dock image here. But how? +} + +- (NSApplicationTerminateReply)allowTerminate +{ + if ([self numDownloadsInProgress] > 0) { - [[self window] performClose:self]; - return; + // make sure the window is visible + [self showWindow:self]; + + NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?"); + NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @""); + NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel"); + NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit"); + + // while the panel is up, download dialogs won't update (no timers firing) but + // downloads continue (PLEvents being processed) + id panel = NSGetAlertPanel(alert, message, okButton, altButton, nil, message); + + [NSApp beginSheet:panel + modalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; + int sheetResult = [NSApp runModalForWindow: panel]; + [NSApp endSheet: panel]; + [panel orderOut: self]; + NSReleaseAlertPanel(panel); + + return (sheetResult == NSAlertDefaultReturn) ? NSTerminateCancel : NSTerminateNow; } - // get the elapsed time - NSArray *elapsedTimeArray = [[mElapsedTimeLabel stringValue] componentsSeparatedByString:@":"]; - int j = [elapsedTimeArray count]; - int elapsedSec = [[elapsedTimeArray objectAtIndex:(j-1)] intValue] + [[elapsedTimeArray objectAtIndex:(j-2)] intValue]*60; - if (j==3) // this download is taking forever. - elapsedSec += [[elapsedTimeArray objectAtIndex:0] intValue]*3600; - // update elapsed time - [mElapsedTimeLabel setStringValue:[self formatTime:(++elapsedSec)]]; - // for status field & time left - float maxBytes = ([mProgressBar maxValue]); - float byteSec = mCurrentProgress/elapsedSec; - // OK - if downloadTimer is nil, we're done - fix maxBytes value for status report. - if (!downloadTimer) - maxBytes = mCurrentProgress; - // update status field - NSString *labelString = NSLocalizedString(@"LabelString",@"%@ of %@ total (at %@/sec)"); - [mStatusLabel setStringValue: [NSString stringWithFormat:labelString, [self formatBytes:mCurrentProgress], [self formatBytes:maxBytes], [self formatBytes:byteSec]]]; - // updating estimated time left field - // if maxBytes < 0, can't calc time left. - // if !downloadTimer, download is finished. either way, make sure time left is 0. - if ((maxBytes > 0) && (downloadTimer)) - { - int secToGo = (int)ceil((elapsedSec*maxBytes/mCurrentProgress) - elapsedSec); - [mTimeLeftLabel setStringValue:[self formatFuzzyTime:secToGo]]; - } - else if (!downloadTimer) - { // download done. Set remaining time to 0, fix progress bar & cancel button - mDownloadIsComplete = YES; // all done. we got a STATE_STOP - [mTimeLeftLabel setStringValue:@""]; - [self setProgressTo:mCurrentProgress ofMax:mCurrentProgress]; - if (!mSaveFileDialogShouldStayOpen || mDoingAutoFileDownload) - [[self window] performClose:self]; // close window - else - [[self window] update]; // redraw window - } - else //maxBytes is undetermined. Set remaining time to question marks. - [mTimeLeftLabel setStringValue:@"???"]; + + return NSTerminateNow; +} + +- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + [NSApp stopModalWithCode:returnCode]; } #pragma mark - -// CHDownloadProgressDisplay protocol methods - -- (void)onStartDownload:(BOOL)isFileSave; +// implement to zoom to a size that just fits the contents +- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame { - mIsFileSave = isFileSave; + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; - [self window]; // make the window - [[self window] setFrameUsingName: ProgressWindowFrameSaveName]; + NSSize curScrollFrameSize = [mScrollView frame].size; + float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height); - [self showWindow: self]; - [self setupDownloadTimer]; - - gNumActiveDownloads++; + NSRect windowFrame = [[self window] frame]; + windowFrame.size.height += frameDelta; + windowFrame.origin.y -= frameDelta; // maintain top + + windowFrame.size.width = mDefaultWindowSize.width; + // cocoa will ensure that the window fits onscreen for us + return windowFrame; } -- (void)onEndDownload +#pragma mark - + +/* + CHStackView datasource methods +*/ + +- (int)subviewsForStackView:(CHStackView *)stackView { - gNumActiveDownloads --; + return [mProgressViewControllers count]; +} + +- (NSView *)viewForStackView:(CHStackView *)aResizingView atIndex:(int)index +{ + return [[mProgressViewControllers objectAtIndex:index] view]; +} + +#pragma mark - + +/* + Just create a progress view, but don't display it (otherwise the URL fields etc. + are just blank) +*/ +- (id )createProgressDisplay +{ + ProgressViewController *newController = [[ProgressViewController alloc] init]; + [newController setProgressWindowController:self]; + [mProgressViewControllers addObject:newController]; - // if we're quitting, our progress window is already gone and we're in the - // process of shutting down gecko and all the d/l listeners. The timer, at - // that point, is the only thing keeping us alive. Killing it will cause - // us to go away immediately, so kung-fu deathgrip it until we're done twiddling - // bits on ourself. - [self retain]; // Enter The Dragon! - [self killDownloadTimer]; - [self setDownloadProgress:nil]; - [self release]; -} - -- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress -{ - mCurrentProgress = aCurProgress; // fall back for stat calcs - - if (![mProgressBar isIndeterminate]) //most likely - just update value - { - if (aCurProgress == aMaxProgress) //handles little bug in FTP download size - [mProgressBar setMaxValue:aMaxProgress]; - - [mProgressBar setDoubleValue:aCurProgress]; - } - else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values - { - [mProgressBar setIndeterminate:NO]; - [mProgressBar setMaxValue:aMaxProgress]; - [mProgressBar setDoubleValue:aCurProgress]; - } // if neither case was true, it's barber pole city. -} - --(void) setDownloadListener: (CHDownloader*)aDownloader -{ - if (mDownloader != aDownloader) - NS_IF_RELEASE(mDownloader); - - NS_IF_ADDREF(mDownloader = aDownloader); -} - -- (void)setSourceURL:(NSString*)aSourceURL -{ - [mFromField setStringValue: aSourceURL]; - [mFromField display]; // force an immmeditate update -} - -- (void)setDestinationPath:(NSString*)aDestPath -{ - [mToField setStringValue: [aDestPath stringByAbbreviatingWithTildeInPath]]; - [mToField display]; // force an immmeditate update - - // also set the window title - NSString* downloadFileName = [aDestPath lastPathComponent]; - if ([downloadFileName length] == 0) - downloadFileName = aDestPath; - - [[self window] setTitle:[NSString stringWithFormat:NSLocalizedString(@"DownloadingTitle", @""), downloadFileName]]; + return newController; } @end diff --git a/camino/src/download/ProgressViewController.h b/camino/src/download/ProgressViewController.h new file mode 100644 index 00000000000..13754722a45 --- /dev/null +++ b/camino/src/download/ProgressViewController.h @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Calum Robinson + * Simon Fraser + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import "CHDownloadProgressDisplay.h" + +class CHDownloader; +@class ProgressDlgController; + +@interface ProgressViewController : NSObject +{ + // we share one progress bar between both views. It's in the expanded + // view by default + IBOutlet NSProgressIndicator *mProgressBar; + + // in-progress expanded view + IBOutlet NSView *mProgressView; + IBOutlet NSButton *mExpandedCancelButton; + + // in-progress collapsed view + IBOutlet NSView *mProgressViewCompact; + + // completed expanded view + IBOutlet NSView *mCompletedView; + IBOutlet NSButton *mExpandedRevealButton; + IBOutlet NSButton *mExpandedOpenButton; + + // completed collapsed view + IBOutlet NSView *mCompletedViewCompact; + + BOOL mViewIsCompact; + BOOL mIsFileSave; + BOOL mUserCancelled; + BOOL mDownloadingError; + BOOL mDownloadDone; + BOOL mRemoveWhenDone; + + NSTimeInterval mDownloadTime; // only set when done + + long mCurrentProgress; // if progress bar is indeterminate, can still calc stats. + long mDownloadSize; + + NSString *mSourceURL; + NSString *mDestPath; + NSDate *mStartTime; + + CHDownloader *mDownloader; // we hold a ref to this + + ProgressDlgController *mProgressWindowController; // not retained +} + ++ (NSString *)formatTime:(int)aSeconds; ++ (NSString *)formatFuzzyTime:(int)aSeconds; ++ (NSString *)formatBytes:(float)aBytes; + +- (NSView *)view; + +- (IBAction)close:(id)sender; + +- (IBAction)stop:(id)sender; +- (IBAction)toggleDisclosure:(id)sender; + +- (IBAction)reveal:(id)sender; +- (IBAction)open:(id)sender; + +- (BOOL)isActive; + +- (void)setProgressWindowController:(ProgressDlgController*)progressWindowController; + +@end diff --git a/camino/src/download/ProgressViewController.mm b/camino/src/download/ProgressViewController.mm new file mode 100644 index 00000000000..86f5fb302db --- /dev/null +++ b/camino/src/download/ProgressViewController.mm @@ -0,0 +1,544 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Calum Robinson + * Simon Fraser + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#import "NSView+Utils.h" + +#import "ProgressViewController.h" +#import "ProgressDlgController.h" +#import "PreferenceManager.h" + +enum +{ + kLabelTagFilename = 1000, + kLabelTagProgress, + kLabelTagSource, + kLabelTagDestination, + kLabelTagTimeRemaining, + kLabelTagStatus, // 1005 + kLabelTagTimeRemainingLabel +}; + + +// Notification sent when user holds option key and expands/contracts a progress view +static NSString *ProgressViewsShouldResize = @"ProgressViewsShouldResize"; + +@interface ProgressViewController(ProgressViewControllerPrivate) + +- (void)viewDidLoad; +- (void)refreshDownloadInfo; +- (void)moveProgressBarToCurrentView; +- (void)updateButtons; + +@end + +@implementation ProgressViewController + ++ (NSString *)formatTime:(int)seconds +{ + NSMutableString *theTime = [NSMutableString stringWithCapacity:8]; + + NSString *padZero = [NSString stringWithString:@"0"]; + //write out new elapsed time + if (seconds >= 3600) + { + [theTime appendFormat:@"%d:",(seconds / 3600)]; + seconds = seconds % 3600; + } + + NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)]; + if ([elapsedMin length] == 2) + [theTime appendString:[padZero stringByAppendingString:elapsedMin]]; + else + [theTime appendString:elapsedMin]; + + seconds = seconds % 60; + NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds]; + + if ([elapsedSec length] == 2) + [theTime appendString:elapsedSec]; + else + [theTime appendString:[padZero stringByAppendingString:elapsedSec]]; + + return theTime; +} + +// fuzzy time gives back strings like "about 5 seconds" ++ (NSString *)formatFuzzyTime:(int)seconds +{ + // check for seconds first + if (seconds < 60) { + if (seconds < 7) + return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 5]; + if (seconds < 13) + return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 10]; + return [NSString stringWithFormat:NSLocalizedString(@"UnderMin", @"Under a minute")]; + } + // seconds becomes minutes and we keep checking. + seconds = seconds/60; + if (seconds < 60) { + if (seconds < 2) + return [NSString stringWithFormat:NSLocalizedString(@"AboutMin",@"About a minute")]; + // OK, tell the good people how much time we have left. + return [NSString stringWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"), seconds]; + } + //this download will never seemingly never end. now seconds become hours. + seconds = seconds/60; + if (seconds < 2) + return [NSString stringWithFormat:NSLocalizedString(@"AboutHour", @"Over an hour")]; + return [NSString stringWithFormat:NSLocalizedString(@"AboutHours", @"Over %d hours"), seconds]; +} + ++ (NSString *)formatBytes:(float)bytes +{ + // if bytes are negative, we return question marks. + if (bytes < 0) + return [NSString stringWithString:@"?"]; + // bytes first. + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f bytes",bytes]; + // kb + bytes = bytes/1024; + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f KB",bytes]; + // mb + bytes = bytes/1024; + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f MB",bytes]; + // gb + bytes = bytes/1024; + return [NSString stringWithFormat:@"%.1f GB",bytes]; +} + +#pragma mark - + +- (id)init +{ + if ((self = [super init])) + { + [NSBundle loadNibNamed:@"ProgressView" owner:self]; + + [self viewDidLoad]; + + // Register for notifications when one of the progress views is expanded/contracted + // whilst holding the option button + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(changeCollapsedStateNotification:) + name:ProgressViewsShouldResize + object:nil]; + + [mExpandedRevealButton setEnabled:NO]; + [mExpandedOpenButton setEnabled:NO]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:ProgressViewsShouldResize + object:nil]; + + // if we get here because we're quitting, the listener will still be alive + // yet we're going away. As a result, we need to tell the d/l listener to + // forget it ever met us and necko will clean it up on its own. + if (mDownloader) + mDownloader->DetachDownloadDisplay(); + NS_IF_RELEASE(mDownloader); + + [mStartTime release]; + [mSourceURL release]; + [mDestPath release]; + [mProgressBar release]; + + [super dealloc]; +} + +// Save the expand/contract view pref (called when the user clicks the dislosure triangle) +- (void)setCompactViewPref +{ + [[PreferenceManager sharedInstance] setPref:"browser.download.compactView" toBoolean:mViewIsCompact]; +} + +- (void)viewDidLoad +{ + mViewIsCompact = [[PreferenceManager sharedInstance] getBooleanPref:"browser.download.compactView" withSuccess:NULL]; + [mProgressBar retain]; // make sure it survives being moved between views + + if (mViewIsCompact) + [self moveProgressBarToCurrentView]; + + // this isn't necessarily better. Need to profile. + [mProgressBar setUsesThreadedAnimation:YES]; +} + +- (NSView *)view +{ + if (mViewIsCompact) + return (mDownloadDone ? mCompletedViewCompact : mProgressViewCompact); + else + return (mDownloadDone ? mCompletedView : mProgressView); +} + +- (IBAction)toggleDisclosure:(id)sender +{ + mViewIsCompact = !mViewIsCompact; + + [self moveProgressBarToCurrentView]; + + // Is option/alt held down? + if ([[[sender window] currentEvent] modifierFlags] & NSAlternateKeyMask) + { + // Get all progress views to look the same as self + [[NSNotificationCenter defaultCenter] postNotificationName:ProgressViewsShouldResize + object:[NSNumber numberWithBool:mViewIsCompact]]; + } + + // Set the pref only when the user clicks the disclosure triangle + [self setCompactViewPref]; + + // Re-calculate the new view & window sizes + [[NSNotificationCenter defaultCenter] postNotificationName:StackViewReloadNotificationName + object:self]; + [self refreshDownloadInfo]; +} + +- (void)changeCollapsedStateNotification:(NSNotification *)notification +{ + // note that this will get called on the view that is being clicked, as well + // as the other views. Don't do redundant work here, like redrawing. + mViewIsCompact = [[notification object] boolValue]; + // Don't call [enclosingStackView reloadSubviews]; here, because it will be done + // by the original view that was option-clicked, not us +} + +-(void)cancel +{ + mUserCancelled = YES; + + if (mDownloader) // we should always have one + mDownloader->CancelDownload(); + + // clean up downloaded file. - do it here or in CancelDownload? + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager isDeletableFileAtPath:mDestPath]) + { + // if we delete it, fantastic. if not, oh well. better to move to trash instead? + [fileManager removeFileAtPath:mDestPath handler:nil]; + } +} + +- (IBAction)close:(id)sender +{ + if (!mDownloadDone) + { + mRemoveWhenDone = YES; + [self cancel]; + } + else + { + [mProgressWindowController removeDownload:self]; + } +} + +- (IBAction)stop:(id)sender +{ + [self cancel]; +} + +- (IBAction)reveal:(id)sender +{ + if ([[NSWorkspace sharedWorkspace] selectFile:mDestPath + inFileViewerRootedAtPath:[mDestPath stringByDeletingLastPathComponent]]) + return; + // hmmm. it didn't work. that's odd. need localized error messages. for now, just beep. + NSBeep(); +} + +- (IBAction)open:(id)sender +{ + if ([[NSWorkspace sharedWorkspace] openFile:mDestPath]) + return; + // hmmm. it didn't work. that's odd. need localized error message. for now, just beep. + NSBeep(); +} + +// Called just before the view will be shown to the user +- (void)downloadDidStart +{ + mStartTime = [[NSDate alloc] init]; +// [mProgressBar startAnimation:self]; // moved to onStartDownload + [self refreshDownloadInfo]; +} + +- (void)downloadDidEnd +{ + mDownloadDone = YES; + mDownloadTime = -[mStartTime timeIntervalSinceNow]; + [mProgressBar stopAnimation:self]; + + [mExpandedCancelButton setEnabled:NO]; + [self refreshDownloadInfo]; +} + +// this handles lots of things. +- (void)refreshDownloadInfo +{ + NSView* curView = [self view]; + + NSString* filename = [mSourceURL lastPathComponent]; + NSString *destPath = [mDestPath stringByAbbreviatingWithTildeInPath]; + NSString* tooltipFormat = NSLocalizedString(mDownloadDone ? @"DownloadedTooltipFormat" : @"DownloadingTooltipFormat", @""); + + id filenameLabel = [curView viewWithTag:kLabelTagFilename]; + [filenameLabel setStringValue:filename]; + [filenameLabel setToolTip:[NSString stringWithFormat:tooltipFormat, [mSourceURL lastPathComponent], mSourceURL, destPath]]; + + id destLabel = [curView viewWithTag:kLabelTagDestination]; + [destLabel setStringValue:destPath]; + + id locationLabel = [curView viewWithTag:kLabelTagSource]; + [locationLabel setStringValue:mSourceURL]; + + if (mDownloadDone) + { + id statusLabel = [curView viewWithTag:kLabelTagStatus]; + if (statusLabel) + { + NSString* statusString; + if (mUserCancelled) + statusString = NSLocalizedString(@"DownloadCancelled", @"Cancelled"); + else if (mDownloadingError) + statusString = NSLocalizedString(@"DownloadInterrupted", @"Interrupted"); + else + statusString = NSLocalizedString(@"DownloadCompleted", @"Completed"); + + [statusLabel setStringValue: statusString]; + } + + // set progress label + id progressLabel = [curView viewWithTag:kLabelTagProgress]; + if (progressLabel) + { + float byteSec = mCurrentProgress / mDownloadTime; + // show how much we downloaded, become some types of disconnects make us think + // we finished successfully + [progressLabel setStringValue:[NSString stringWithFormat: + NSLocalizedString(@"DownloadDoneStatusString", @"%@ of %@ done (at %@/sec)"), + [[self class] formatBytes:mCurrentProgress], + [[self class] formatBytes:mDownloadSize], + [[self class] formatBytes:byteSec]]]; + } + + id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining]; + if (timeLabel) + [timeLabel setStringValue:[[self class] formatTime:(int)mDownloadTime]]; + + id timeLabelLabel = [curView viewWithTag:kLabelTagTimeRemainingLabel]; + if (timeLabelLabel) + [timeLabelLabel setStringValue:NSLocalizedString(@"DownloadRemainingLabelDone", @"Time elapsed:")]; + + [self updateButtons]; + } + else + { + NSTimeInterval elapsedTime = -[mStartTime timeIntervalSinceNow]; + + // update status field + id progressLabel = [curView viewWithTag:kLabelTagProgress]; + if (progressLabel) + { + NSString *statusLabelString = NSLocalizedString(@"DownloadStatusString", @"%@ of %@ total (at %@/sec)"); + float byteSec = mCurrentProgress / elapsedTime; + [progressLabel setStringValue:[NSString stringWithFormat:statusLabelString, + [[self class] formatBytes:mCurrentProgress], + (mDownloadSize > 0 ? [[self class] formatBytes:mDownloadSize] : @"?"), + [[self class] formatBytes:byteSec]]]; + } + + id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining]; + if (timeLabel) + { + if (mDownloadSize > 0) + { + int secToGo = (int)ceil((elapsedTime * mDownloadSize / mCurrentProgress) - elapsedTime); + [timeLabel setStringValue:[[self class] formatFuzzyTime:secToGo]]; + } + else // mDownloadSize is undetermined. Set remaining time to question marks. + { + NSString *calculatingString = NSLocalizedString(@"DownloadCalculatingString", @"Unknown"); + [timeLabel setStringValue:calculatingString]; + } + } + } +} + +- (void)updateButtons +{ + // note: this will stat every time, which will be expensive! We could use + // FNNotify/FNSubscribe to avoid this (writing a Cocoa wrapper around it). + if (mDownloadDone && !mDownloadingError) + { + BOOL destFileExists = [[NSFileManager defaultManager] fileExistsAtPath:mDestPath]; + [mExpandedRevealButton setEnabled:destFileExists]; + [mExpandedOpenButton setEnabled:destFileExists]; + } +} + +- (void)moveProgressBarToCurrentView +{ + [mProgressBar moveToView:(mViewIsCompact ? mProgressViewCompact : mProgressView) resize:YES]; + [mProgressBar startAnimation:self]; // this is necessary to keep it animating for some reason +} + +- (void)setProgressWindowController:(ProgressDlgController*)progressWindowController +{ + mProgressWindowController = progressWindowController; +} + +- (BOOL)isActive +{ + return !mDownloadDone; +} + +#pragma mark - + +- (void)onStartDownload:(BOOL)isFileSave +{ + mIsFileSave = isFileSave; + [self downloadDidStart]; + [mProgressWindowController didStartDownload:self]; + + // need to do this after the view as been put in the window, otherwise it doesn't work + [mProgressBar startAnimation:self]; +} + +- (void)onEndDownload:(BOOL)completedOK +{ + mDownloadingError = !completedOK; + + [self downloadDidEnd]; + [mProgressWindowController didEndDownload:self]; + if (mRemoveWhenDone) + [mProgressWindowController removeDownload:self]; +} + +- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress +{ + mCurrentProgress = aCurProgress; // fall back for stat calcs + mDownloadSize = aMaxProgress; + + if (![mProgressBar isIndeterminate]) //most likely - just update value + { + if (aCurProgress == aMaxProgress) //handles little bug in FTP download size + [mProgressBar setMaxValue:aMaxProgress]; + + [mProgressBar setDoubleValue:aCurProgress]; + } + else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values + { + [mProgressBar setIndeterminate:NO]; + [mProgressBar setMaxValue:aMaxProgress]; + [mProgressBar setDoubleValue:aCurProgress]; + } // if neither case was true, it's barber pole city. +} + +-(void)setDownloadListener:(CHDownloader*)aDownloader +{ + if (mDownloader != aDownloader) + NS_IF_RELEASE(mDownloader); + + NS_IF_ADDREF(mDownloader = aDownloader); +} + +#if 0 +/* + This is kind of a hack. It should probably be done somewhere else so Mozilla can have + it too, but until Apple fixes the problems with the setting of comments without + reverting to Applescript, I have left it in. + + Turned off for now, until we find a better way to do this. Won't Carbon APIs work? +*/ +- (void)tryToSetFinderComments +{ + if (mDestPath && mSourceURL) + { + CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL, + (CFStringRef)mDestPath, + kCFURLPOSIXPathStyle, + NO); + + NSString *hfsPath = (NSString *)CFURLCopyFileSystemPath(fileURL, + kCFURLHFSPathStyle); + + CFRelease(fileURL); + + NSAppleScript *setCommentScript = [[NSAppleScript alloc] initWithSource: + [NSString stringWithFormat:@"tell application \"Finder\" to set comment of file \"%@\" to \"%@\"", hfsPath, mSourceURL]]; + NSDictionary *errorInfo = NULL; + + [setCommentScript executeAndReturnError:&errorInfo]; + + if (errorInfo) + { + NSLog(@"Get error when running AppleScript to set comments for '%@':\n %@", + mDestPath, + [errorInfo objectForKey:NSAppleScriptErrorMessage]); + } + } +} +#endif + +- (void)setSourceURL:(NSString*)aSourceURL +{ + [mSourceURL autorelease]; + mSourceURL = [aSourceURL copy]; + + //[self tryToSetFinderComments]; +} + +- (void)setDestinationPath:(NSString*)aDestPath +{ + [mDestPath autorelease]; + mDestPath = [aDestPath copy]; + //[self tryToSetFinderComments]; +} + +@end diff --git a/camino/src/download/SaveHeaderSniffer.h b/camino/src/download/SaveHeaderSniffer.h index 4147cce1507..4ae0c1c04bb 100644 --- a/camino/src/download/SaveHeaderSniffer.h +++ b/camino/src/download/SaveHeaderSniffer.h @@ -56,7 +56,7 @@ public: nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData, const nsAString& aSuggestedFilename, PRBool aBypassCache, - NSView* aFilterView, NSPopUpButton* aFilterList); + NSView* aFilterView); virtual ~nsHeaderSniffer(); NS_DECL_ISUPPORTS @@ -79,6 +79,5 @@ private: nsCString mContentType; nsCString mContentDisposition; NSView* mFilterView; - NSPopUpButton* mFilterList; }; diff --git a/camino/src/download/SaveHeaderSniffer.mm b/camino/src/download/SaveHeaderSniffer.mm index 42827fa633c..77ccd5842d7 100644 --- a/camino/src/download/SaveHeaderSniffer.mm +++ b/camino/src/download/SaveHeaderSniffer.mm @@ -38,6 +38,8 @@ #import "NSString+Utils.h" +#import "ChimeraUIConstants.h" + #include "SaveHeaderSniffer.h" #include "netCore.h" @@ -56,7 +58,7 @@ const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrows nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData, const nsAString& aSuggestedFilename, PRBool aBypassCache, - NSView* aFilterView, NSPopUpButton* aFilterList) + NSView* aFilterView) : mPersist(aPersist) , mTmpFile(aFile) , mURL(aURL) @@ -65,9 +67,8 @@ nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, , mDefaultFilename(aSuggestedFilename) , mBypassCache(aBypassCache) , mFilterView(aFilterView) -, mFilterList(aFilterList) { - NS_INIT_ISUPPORTS(); + NS_INIT_ISUPPORTS(); } nsHeaderSniffer::~nsHeaderSniffer() @@ -183,14 +184,16 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) return rv; nsCOMPtr dirBranch; prefs->GetBranch("browser.download.", getter_AddRefs(dirBranch)); - PRInt32 filterIndex = 0; + PRInt32 filterIndex = eSaveFormatHTMLComplete; if (dirBranch) { nsresult rv = dirBranch->GetIntPref("save_converter_index", &filterIndex); if (NS_FAILED(rv)) - filterIndex = 0; + filterIndex = eSaveFormatHTMLComplete; } - if (mFilterList) - [mFilterList selectItemAtIndex: filterIndex]; + + NSPopUpButton* filterList = [mFilterView viewWithTag:kSaveFormatPopupTag]; + if (filterList) + [filterList selectItemAtIndex: filterIndex]; // We need to figure out what file name to use. nsAutoString defaultFileName; @@ -294,17 +297,17 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) return NS_OK; // Update the filter index. - if (isHTML && mFilterList) { - filterIndex = [mFilterList indexOfSelectedItem]; + if (isHTML && filterList) { + filterIndex = [filterList indexOfSelectedItem]; dirBranch->SetIntPref("save_converter_index", filterIndex); } // Convert the content type to text/plain if it was selected in the filter. - if (isHTML && filterIndex == 2) + if (isHTML && filterIndex == eSaveFormatPlainText) mContentType = "text/plain"; nsCOMPtr sourceData; - if (isHTML && filterIndex != 1) + if (isHTML && filterIndex != eSaveFormatHTMLSource) sourceData = do_QueryInterface(mDocument); else sourceData = do_QueryInterface(mURL); diff --git a/camino/src/download/nsDownloadListener.h b/camino/src/download/nsDownloadListener.h index c76874c71d9..d3dc4e47aa7 100644 --- a/camino/src/download/nsDownloadListener.h +++ b/camino/src/download/nsDownloadListener.h @@ -21,6 +21,7 @@ * * Contributor(s): * Simon Fraser + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -49,6 +50,8 @@ #include "nsIWebBrowserPersist.h" #include "nsIURI.h" #include "nsILocalFile.h" +#include "nsITimer.h" + #include "nsExternalHelperAppService.h" @@ -56,24 +59,28 @@ class nsDownloadListener : public CHDownloader, public nsIDownload, - public nsIWebProgressListener + public nsIWebProgressListener, + public nsITimerCallback { public: - nsDownloadListener(DownloadControllerFactory* inDownloadControllerFactory); + nsDownloadListener(); virtual ~nsDownloadListener(); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOWNLOAD NS_DECL_NSIWEBPROGRESSLISTENER + + // nsITimerCallback + NS_IMETHOD Notify(nsITimer *timer); public: - //void BeginDownload(); + void InitDialog(); virtual void PauseDownload(); virtual void ResumeDownload(); virtual void CancelDownload(); - virtual void DownloadDone(); + virtual void DownloadDone(nsresult aStatus); virtual void DetachDownloadDisplay(); private: @@ -84,10 +91,13 @@ private: nsCOMPtr mURI; // The URI of our source file. Null if we're saving a complete document. nsCOMPtr mDestination; // Our destination URL. + nsCOMPtr mEndRefreshTimer; // Timer used to update the status to done + nsresult mDownloadStatus; // status from last nofication PRInt64 mStartTime; // When the download started PRPackedBool mBypassCache; // Whether we should bypass the cache or not. PRPackedBool mNetworkTransfer; // true if the first OnStateChange has the NETWORK bit set PRPackedBool mGotFirstStateChange; // true after we've seen the first OnStateChange PRPackedBool mUserCanceled; // true if the user canceled the download + PRPackedBool mSentCancel; // true when we've notified the backend of the cancel }; diff --git a/camino/src/download/nsDownloadListener.mm b/camino/src/download/nsDownloadListener.mm index 8acb6b28c53..0fb52f20c6a 100644 --- a/camino/src/download/nsDownloadListener.mm +++ b/camino/src/download/nsDownloadListener.mm @@ -21,7 +21,7 @@ * * Contributor(s): * Simon Fraser - * + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -46,20 +46,25 @@ #include "nsIURL.h" #include "netCore.h" -nsDownloadListener::nsDownloadListener(DownloadControllerFactory* inControllerFactory) -: CHDownloader(inControllerFactory) +nsDownloadListener::nsDownloadListener() +: mDownloadStatus(NS_OK) , mBypassCache(PR_FALSE) , mNetworkTransfer(PR_FALSE) , mGotFirstStateChange(PR_FALSE) , mUserCanceled(PR_FALSE) +, mSentCancel(PR_FALSE) { + mStartTime = LL_ZERO; } nsDownloadListener::~nsDownloadListener() { + // if we go away before the timer fires, cancel it + if (mEndRefreshTimer) + mEndRefreshTimer->Cancel(); } -NS_IMPL_ISUPPORTS_INHERITED2(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener) +NS_IMPL_ISUPPORTS_INHERITED3(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener, nsITimerCallback) #pragma mark - @@ -193,14 +198,14 @@ nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { - if (mUserCanceled) + if (mUserCanceled && !mSentCancel) { if (mHelperAppLauncher) mHelperAppLauncher->Cancel(); else if (aRequest) aRequest->Cancel(NS_BINDING_ABORTED); - mUserCanceled = false; + mSentCancel = PR_TRUE; } [mDownloadDisplay setProgressTo:aCurTotalProgress ofMax:aMaxTotalProgress]; @@ -236,7 +241,7 @@ nsDownloadListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *a // Implementation of nsIWebProgressListener /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in unsigned long aStatus); */ NS_IMETHODIMP -nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, +nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, PRUint32 aStatus) { // NSLog(@"State changed: state %u, status %u", aStateFlags, aStatus); @@ -250,29 +255,64 @@ nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRe // the window and controller. We will get this even in the event of a cancel, // so this is the only place in the listener where we should kill the download. if ((aStateFlags & STATE_STOP) && (!mNetworkTransfer || (aStateFlags & STATE_IS_NETWORK))) { - DownloadDone(); + DownloadDone(aStatus); } return NS_OK; } #pragma mark - +// nsITimerCallback implementation +NS_IMETHODIMP nsDownloadListener::Notify(nsITimer *timer) +{ + // resset the destination, since uniquifying the filename may have + // changed it + nsAutoString pathStr; + mDestination->GetPath(pathStr); + [mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]]; + + // cancelling should give us a failure status + [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(mDownloadStatus) && !mUserCanceled)]; + mEndRefreshTimer = NULL; + return NS_OK; +} + +#pragma mark - + void nsDownloadListener::InitDialog() { // dialog has to be shown before the outlets get hooked up - [mDownloadDisplay onStartDownload:(BOOL)IsFileSave()]; - if (mURI) { nsCAutoString spec; - mURI->GetSpec(spec); + + // we need to be careful not to show a password in the url + nsCAutoString userPassword; + mURI->GetUserPass(userPassword); + if (!userPassword.IsEmpty()) + { + // ugh, build it by hand + nsCAutoString hostport, path; + mURI->GetScheme(spec); + mURI->GetHostPort(hostport); + mURI->GetPath(path); + + spec.Append("://"); + spec.Append(hostport); + spec.Append(path); + } + else + mURI->GetSpec(spec); + [mDownloadDisplay setSourceURL: [NSString stringWithUTF8String:spec.get()]]; } nsAutoString pathStr; mDestination->GetPath(pathStr); [mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]]; + + [mDownloadDisplay onStartDownload:IsFileSave()]; } void @@ -292,19 +332,19 @@ nsDownloadListener::CancelDownload() { mUserCanceled = PR_TRUE; - if (mWebPersist) + if (mWebPersist && !mSentCancel) { mWebPersist->CancelSave(); - mUserCanceled = PR_FALSE; + mSentCancel = PR_TRUE; } // delete any files we've created... - + // DownloadDone will get called (eventually) } void -nsDownloadListener::DownloadDone() +nsDownloadListener::DownloadDone(nsresult aStatus) { // break the reference cycle by removing ourselves as a listener if (mWebPersist) @@ -314,8 +354,23 @@ nsDownloadListener::DownloadDone() } mHelperAppLauncher = nsnull; - - [mDownloadDisplay onEndDownload]; + mDownloadStatus = aStatus; + + // hack alert! + // Our destination file gets uniquified after the OnStop notification is sent + // (in nsExternalAppHandler::ExecuteDesiredAction), so we never get a chance + // to figure out the final filename. To work around this, set a timer to fire + // in the near future, from which we'll send the done callback. + mEndRefreshTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (mEndRefreshTimer) + { + nsresult rv = mEndRefreshTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT); // defaults to 1-shot, normal priority + if (NS_FAILED(rv)) + mEndRefreshTimer = NULL; + } + + if (!mEndRefreshTimer) // timer creation or init failed, so just do it now + [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(aStatus) && !mUserCanceled)]; } // diff --git a/camino/src/embedding/CHBrowserService.mm b/camino/src/embedding/CHBrowserService.mm index 0026795c567..6c0133b34e2 100644 --- a/camino/src/embedding/CHBrowserService.mm +++ b/camino/src/embedding/CHBrowserService.mm @@ -38,7 +38,6 @@ #import "NSString+Utils.h" #import "CHBrowserService.h" -#import "CHDownloadFactories.h" #import "CHBrowserView.h" #include "nsIWindowWatcher.h" @@ -107,14 +106,6 @@ CHBrowserService::InitEmbedding() static NS_DEFINE_CID(kHelperDlgCID, NS_HELPERAPPLAUNCHERDIALOG_CID); nsresult rv = cr->RegisterFactory(kHelperDlgCID, NS_IHELPERAPPLAUNCHERDLG_CLASSNAME, NS_IHELPERAPPLAUNCHERDLG_CONTRACTID, sSingleton); - - // replace the downloader with our own which does not rely on the xpfe downlaod manager - nsCOMPtr downloadFactory; - rv = NewDownloadListenerFactory(getter_AddRefs(downloadFactory)); - if (NS_FAILED(rv)) return rv; - - static NS_DEFINE_CID(kDownloadCID, NS_DOWNLOAD_CID); - rv = cr->RegisterFactory(kDownloadCID, "Download", NS_DOWNLOAD_CONTRACTID, downloadFactory); return rv; } diff --git a/camino/src/embedding/CHBrowserView.h b/camino/src/embedding/CHBrowserView.h index c7f87ee2b90..ff000640c7e 100644 --- a/camino/src/embedding/CHBrowserView.h +++ b/camino/src/embedding/CHBrowserView.h @@ -163,9 +163,8 @@ enum { // nsIWebBrowserSetup methods - (void)setProperty:(unsigned int)property toValue:(unsigned int)value; -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList; -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView; +- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; - (void)printDocument; - (void)pageSetup; diff --git a/camino/src/embedding/CHBrowserView.mm b/camino/src/embedding/CHBrowserView.mm index 43feb519bee..4179f8260eb 100644 --- a/camino/src/embedding/CHBrowserView.mm +++ b/camino/src/embedding/CHBrowserView.mm @@ -430,7 +430,6 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; suggestedFilename: (NSString*)aFileName bypassCache: (BOOL)aBypassCache filterView: (NSView*)aFilterView - filterList: (NSPopUpButton*)aFilterList { // Create our web browser persist object. This is the object that knows // how to actually perform the saving of the page (and of the images @@ -477,7 +476,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; [aFileName assignTo_nsAString:fileName]; nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI, aDocument, postData, fileName, aBypassCache, - aFilterView, aFilterList); + aFilterView); if (!sniffer) return; webPersist->SetProgressListener(sniffer); // owned @@ -572,8 +571,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; return found; } -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename +- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename { nsCOMPtr url; nsresult rv = NS_NewURI(getter_AddRefs(url), [aURLSpec UTF8String]); @@ -584,8 +582,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; withDocument: nsnull suggestedFilename: aFilename bypassCache: YES - filterView: aFilterView - filterList: aFilterList]; + filterView: aFilterView]; } -(NSString*)getFocusedURLString @@ -616,7 +613,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; return [NSString stringWith_nsAString: urlStr]; } -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView { if (!_webBrowser) return; @@ -656,8 +653,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; withDocument: domDocument suggestedFilename: @"" bypassCache: NO - filterView: aFilterView - filterList: aFilterList]; + filterView: aFilterView]; } -(void)doCommand:(const char*)commandName diff --git a/camino/src/embedding/CHDownloadProgressDisplay.h b/camino/src/embedding/CHDownloadProgressDisplay.h index 03b8e659354..f1912e1dd8b 100644 --- a/camino/src/embedding/CHDownloadProgressDisplay.h +++ b/camino/src/embedding/CHDownloadProgressDisplay.h @@ -20,6 +20,7 @@ * * Contributor(s): * Simon Fraser + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -45,19 +46,17 @@ 1. The CHDownloadProgressDisplay protocol. This is a formal protocol that needs to be implemented by - a window controller for your progress window. Its methods - will be called by the underlying C++ downloading classes. + an object (eg. a window controller or a view controller) + for your progress window. Its methods will be called by the + underlying C++ downloading classes. - 2. The Obj-C DownloadControllerFactory class. - - This class should be subclassed by an embedder, with an - implementation of 'createDownloadController' that hands back - a new instance of an NSWindowController that implements the - protocol. - - The underlying C++ classes use this factory to create the - progress window controller. + 2. The CHDownloadDisplayFactory protocol + This is a formal protocol that can be implemented by + any object that can create objects that themselves + implement CHDownloadProgressDisplay. This would probably be + an NSWindowController. + 3. The CHDownloader C++ class This base class exists to hide the complextity of the download @@ -90,10 +89,10 @@ In both cases, creating the nsDownloadListener and calling its Init() method calls nsDownloder::CreateDownloadDisplay(). The nsDownloder has as a member - variable a DownloadControllerFactory (see above), which got passed to it - via our XPCOM factory for nsIDownload objects. It then uses that DownloadControllerFactory - to get an instance of the download progress window controller, which then - shows the download progress window. + variable an object that implements CHDownloadDisplayFactory (see above), which got set + on it via a call to SetDisplayFactory. It then uses that CHDownloadDisplayFactory + to create an instance of the download progress display, which then controls + something (like a view or window) that shows in the UI. Simple, eh? @@ -105,13 +104,13 @@ class CHDownloader; -// a formal protocol for something that implements progress display -// Embedders can make a window controller that conforms to this +// A formal protocol for something that implements progress display. +// Embedders can make a window or view controller that conforms to this // protocol, and reuse nsDownloadListener to get download UI. @protocol CHDownloadProgressDisplay - (void)onStartDownload:(BOOL)isFileSave; -- (void)onEndDownload; +- (void)onEndDownload:(BOOL)completedOK; - (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress; @@ -121,35 +120,34 @@ class CHDownloader; @end -// subclass this, and have your subclass instantiate and return your window -// controller in createDownloadController -@interface DownloadControllerFactory : NSObject -{ -} +// A formal protocol which is implemented by a factory of progress UI. +@protocol CHDownloadDisplayFactory -- (NSWindowController *)createDownloadController; +- (id )createProgressDisplay; @end // Pure virtual base class for a generic downloader, that the progress UI can talk to. // It implements nsISupports so that it can be refcounted. This class insulates the -// UI code from having to know too much about the nsIDownloadListener. -// It is responsible for creating the download UI, via the DownloadControllerFactory +// UI code from having to know too much about the nsDownloadListener. +// It is responsible for creating the download UI, via the CHDownloadController // that it owns. class CHDownloader : public nsISupports { public: - CHDownloader(DownloadControllerFactory* inControllerFactory); + CHDownloader(); virtual ~CHDownloader(); NS_DECL_ISUPPORTS + virtual void SetDisplayFactory(id inDownloadDisplayFactory); // retains + virtual void PauseDownload() = 0; virtual void ResumeDownload() = 0; virtual void CancelDownload() = 0; - virtual void DownloadDone() = 0; - virtual void DetachDownloadDisplay() = 0; // tell downloader to forget about its display + virtual void DownloadDone(nsresult aStatus) = 0; + virtual void DetachDownloadDisplay() = 0; // tell downloader to forget about its display virtual void CreateDownloadDisplay(); @@ -160,8 +158,8 @@ protected: protected: - DownloadControllerFactory* mControllerFactory; - id mDownloadDisplay; // something that implements the CHDownloadProgressDisplay protocol - PRBool mIsFileSave; // true if we're doing a save, rather than a download + id mDisplayFactory; + id mDownloadDisplay; // something that implements the CHDownloadProgressDisplay protocol + PRBool mIsFileSave; // true if we're doing a save, rather than a download }; diff --git a/camino/src/embedding/CHDownloadProgressDisplay.mm b/camino/src/embedding/CHDownloadProgressDisplay.mm index 3f384b9fa90..18a7e3df922 100644 --- a/camino/src/embedding/CHDownloadProgressDisplay.mm +++ b/camino/src/embedding/CHDownloadProgressDisplay.mm @@ -20,6 +20,7 @@ * * Contributor(s): * Simon Fraser + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,40 +38,34 @@ #import "CHDownloadProgressDisplay.h" +// CHDownloader is a simple class that that the download UI can talk to -@implementation DownloadControllerFactory - -- (NSWindowController *)createDownloadController -{ - // a dummy implementation. You should provide a subclass that - // returns an instance of your progress dialog controller. - return nil; -} - -@end - -#pragma mark - - -// see the header file for comments -CHDownloader::CHDownloader(DownloadControllerFactory* inControllerFactory) -: mControllerFactory(inControllerFactory) +CHDownloader::CHDownloader() +: mDisplayFactory(NULL) , mDownloadDisplay(nil) , mIsFileSave(PR_FALSE) { NS_INIT_ISUPPORTS(); - [mControllerFactory retain]; } CHDownloader::~CHDownloader() { - [mControllerFactory release]; + [mDisplayFactory release]; } NS_IMPL_ISUPPORTS1(CHDownloader, nsISupports); +void +CHDownloader::SetDisplayFactory(id inDownloadControllerFactory) +{ + mDisplayFactory = inDownloadControllerFactory; + [mDisplayFactory retain]; +} + void CHDownloader::CreateDownloadDisplay() { - mDownloadDisplay = [mControllerFactory createDownloadController]; + NS_ASSERTION(mDisplayFactory, "Should have a UI factory"); + mDownloadDisplay = [mDisplayFactory createProgressDisplay]; [mDownloadDisplay setDownloadListener:this]; } diff --git a/camino/src/extensions/CHStackView.h b/camino/src/extensions/CHStackView.h new file mode 100644 index 00000000000..34149ed253d --- /dev/null +++ b/camino/src/extensions/CHStackView.h @@ -0,0 +1,61 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Chimera code. + * + * The Initial Developer of the Original Code is + * Calum Robinson. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Calum Robinson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import + +// views contained in the stack should send this notification when they change size +extern NSString* StackViewReloadNotificationName; + +// the stack view sends this notification after it has adjusted to subview sizes +extern NSString* StackViewResizedNotificationName; + +@interface CHStackView : NSView +{ + IBOutlet id mDataSource; +} + +- (void)setDataSource:(id)aDataSource; +- (void)reloadSubviews; + +@end + +@protocol CHStackViewDataSource + +- (int)subviewsForStackView:(CHStackView *)stackView; +- (NSView *)viewForStackView:(CHStackView *)stackView atIndex:(int)index; + +@end diff --git a/camino/src/extensions/CHStackView.m b/camino/src/extensions/CHStackView.m new file mode 100644 index 00000000000..d14c0d87e86 --- /dev/null +++ b/camino/src/extensions/CHStackView.m @@ -0,0 +1,143 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Chimera code. + * + * The Initial Developer of the Original Code is + * Calum Robinson. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Calum Robinson + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + /* + This class was inspired by the OAStack view from OmniGroup, but not copied directly. This + implementation is a little simpler, which is fine. + + It's like NSTableView, except the data source returns views instead of strings/images etc. +*/ + +#import "CHStackView.h" + +NSString* StackViewReloadNotificationName = @"ReloadStackView"; +NSString* StackViewResizedNotificationName = @"StackViewResized"; + +@implementation CHStackView + +- (id)initWithFrame:(NSRect)frameRect +{ + if ((self = [super initWithFrame:frameRect])) + { + // Register for notifications when one of the subviews changes size + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(reloadNotification:) + name:StackViewReloadNotificationName + object:nil]; + + } + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)setDataSource:(id)aDataSource +{ + mDataSource = aDataSource; // should this retain? + + [self reloadSubviews]; +} + +- (void)reloadNotification:(NSNotification *)notification +{ + [self reloadSubviews]; +} + +- (void)reloadSubviews +{ + NSRect newFrame = [self frame]; + NSSize oldSize = [self bounds].size; + int i, subviewCount = [mDataSource subviewsForStackView:self]; + + NSPoint nextOrigin = NSZeroPoint; + + // we'll maintain the width of the stack view, assuming that it's + // scaled by its superview. + newFrame.size.height = 0.0; + + [[self subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + for (i = 0; i < subviewCount; i++) + { + NSView *subview = [mDataSource viewForStackView:self atIndex:i]; + NSRect subviewFrame = [subview frame]; + + unsigned int autoResizeMask = [subview autoresizingMask]; + if (autoResizeMask & NSViewWidthSizable) + subviewFrame.size.width = newFrame.size.width; + + newFrame.size.height += NSHeight(subviewFrame); + + subviewFrame.origin = nextOrigin; + [subview setFrame:subviewFrame]; + nextOrigin.y += NSHeight(subviewFrame); + + [self addSubview:subview]; + + // If there are more subviews, add a separator + if (i + 1 < subviewCount) + { + NSBox *separator = [[NSBox alloc] initWithFrame: + NSMakeRect(nextOrigin.x, nextOrigin.y - 1.0, NSWidth([subview frame]), 1.0)]; + [separator setBoxType:NSBoxSeparator]; + [separator setAutoresizingMask:NSViewWidthSizable]; + [self addSubview:separator]; + [separator release]; + } + } + + NSRect newBounds = newFrame; + newBounds.origin = NSZeroPoint; + + [self setFrame:newFrame]; + [self setNeedsDisplay:YES]; + + [[NSNotificationCenter defaultCenter] postNotificationName:StackViewResizedNotificationName + object:self + userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithSize:oldSize], @"oldsize", nil]]; +} + +- (BOOL)isFlipped +{ + return YES; +} + +@end diff --git a/camino/src/extensions/NSView+Utils.h b/camino/src/extensions/NSView+Utils.h new file mode 100644 index 00000000000..c36e552813f --- /dev/null +++ b/camino/src/extensions/NSView+Utils.h @@ -0,0 +1,60 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Chimera code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Simon Fraser + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import + +#ifdef __cplusplus +extern "C" { +#endif + +// utility routine; returns YES if the sizes are equal, with the given slop +BOOL CHCloseSizes(NSSize aSize, NSSize bSize, float slop); + +#ifdef __cplusplus +} +#endif + +// category on NSView to add utilities for easy view resizing etc. + +@interface NSView(CHViewUtils) + +// move the recipient view from its superview to the destView, +// maintaining the relative size and position of the view based +// on its autoresize flags. +- (void)moveToView:(NSView*)destView resize:(BOOL)resize; + +@end diff --git a/camino/src/extensions/NSView+Utils.m b/camino/src/extensions/NSView+Utils.m new file mode 100644 index 00000000000..21393098095 --- /dev/null +++ b/camino/src/extensions/NSView+Utils.m @@ -0,0 +1,154 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Chimera code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Simon Fraser + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#import "NSView+Utils.h" + +BOOL CHCloseSizes(NSSize aSize, NSSize bSize, float slop) +{ + return (fabs(aSize.width - bSize.width) <= slop) && + (fabs(aSize.height - bSize.height) <= slop); +} + +// mask has 3 bits: 0 = 1 scales, 1 = 2 scales, 2 = 3 scales. +static void RedistributeSpace(int resizeMask, float newWidth, /* in out */ float ioSpaces[3]) +{ + float oldWidth = ioSpaces[0] + ioSpaces[1] + ioSpaces[2]; + + if (resizeMask != 0) + { + switch (resizeMask) + { + // 1 scalable section + case 1: // first + ioSpaces[0] += newWidth - oldWidth; // it can go negative + break; + case 2: // middle + ioSpaces[1] += newWidth - oldWidth; // it can go negative + break; + case 4: // last + ioSpaces[2] += newWidth - oldWidth; // it can go negative + break; + + // 2 scalable sections + case 3: // last fixed + { + float oldScaledWidth = ioSpaces[0] + ioSpaces[1]; + float newScaledWidth = (newWidth - ioSpaces[2]); + ioSpaces[0] = newScaledWidth * (ioSpaces[0] / oldScaledWidth); + ioSpaces[1] = newScaledWidth * (ioSpaces[1] / oldScaledWidth); + break; + } + case 5: // middle fixed + { + float oldScaledWidth = ioSpaces[0] + ioSpaces[2]; + float newScaledWidth = (newWidth - ioSpaces[1]); + ioSpaces[0] = newScaledWidth * (ioSpaces[0] / oldScaledWidth); + ioSpaces[2] = newScaledWidth * (ioSpaces[2] / oldScaledWidth); + break; + } + case 6: // first fixed + { + float oldScaledWidth = ioSpaces[1] + ioSpaces[2]; + float newScaledWidth = (newWidth - ioSpaces[0]); + ioSpaces[1] = newScaledWidth * (ioSpaces[1] / oldScaledWidth); + ioSpaces[2] = newScaledWidth * (ioSpaces[2] / oldScaledWidth); + break; + } + + // all scalable + case 7: + ioSpaces[0] *= newWidth / oldWidth; + ioSpaces[1] *= newWidth / oldWidth; + ioSpaces[2] *= newWidth / oldWidth; + break; + } + } + // otherwise nothing changes +} + +@implementation NSView(CHViewUtils) + +- (void)moveToView:(NSView*)destView resize:(BOOL)resize +{ + //resize &= [destView autoresizesSubviews]; + + NSRect oldFrame = [self frame]; + NSRect oldSuperBounds = [[self superview] bounds]; + + [self retain]; + [self removeFromSuperview]; + + [destView addSubview:self]; + [self release]; + + [destView setAutoresizesSubviews:YES]; + + if (resize) + { + unsigned int resizeMask = [self autoresizingMask]; + NSRect newFrame = oldFrame; + + if (resizeMask != NSViewNotSizable && !NSEqualRects([destView bounds], oldSuperBounds)) + { + float spaces[3]; + // horizontal + float newWidth = NSWidth([destView bounds]); + spaces[0] = NSMinX(oldFrame); + spaces[1] = NSWidth(oldFrame); + spaces[2] = NSMaxX(oldSuperBounds) - NSMaxX(oldFrame); + + RedistributeSpace(resizeMask & 0x07, newWidth, spaces); + newFrame.origin.x = spaces[0]; + newFrame.size.width = spaces[1]; + + // vertical. we assume that the view should stick to the top of the destView here + float newHeight = NSHeight([destView bounds]); + spaces[0] = NSMinY(oldFrame); + spaces[1] = NSHeight(oldFrame); + spaces[2] = NSMaxY(oldSuperBounds) - NSMaxY(oldFrame); + + RedistributeSpace((resizeMask >> 3) & 0x07, newHeight, spaces); + newFrame.origin.y = spaces[0]; + newFrame.size.height = spaces[1]; + } + + [self setFrame:newFrame]; + [self setNeedsDisplay:YES]; + } +} + +@end diff --git a/camino/src/extensions/RDFOutlineViewDataSource.h b/camino/src/extensions/RDFOutlineViewDataSource.h index f75ab400132..81c6ce491ce 100644 --- a/camino/src/extensions/RDFOutlineViewDataSource.h +++ b/camino/src/extensions/RDFOutlineViewDataSource.h @@ -51,24 +51,31 @@ class nsIRDFService; @interface RDFOutlineViewItem : NSObject { nsIRDFResource* mResource; + unsigned int mCacheVersion; // if matches the cache version in the data source, + // cached values are valid + BOOL mExpandable; + int mNumChildren; + NSArray* mChildNodes; } -- (nsIRDFResource*) resource; -- (void) setResource: (nsIRDFResource*) aResource; +- (nsIRDFResource*)resource; // addRefs the result +- (void)setResource:(nsIRDFResource*) aResource; @end -@interface RDFOutlineViewDataSource : NSObject { - nsIRDFDataSource* mDataSource; - nsIRDFContainer* mContainer; - nsIRDFContainerUtils* mContainerUtils; - nsIRDFResource* mRootResource; - nsIRDFService* mRDFService; +@interface RDFOutlineViewDataSource : NSObject +{ + nsIRDFDataSource* mDataSource; + nsIRDFContainer* mContainer; + nsIRDFContainerUtils* mContainerUtils; + nsIRDFResource* mRootResource; + nsIRDFService* mRDFService; - IBOutlet ExtendedOutlineView* mOutlineView; + IBOutlet ExtendedOutlineView* mOutlineView; - NSMutableDictionary* mDictionary; + NSMutableDictionary* mDictionary; + unsigned int mCacheVersion; } // Initialization Methods @@ -85,7 +92,6 @@ class nsIRDFService; - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item; - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item; - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; -- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; // tooltip support from the ExtendedOutlineView. Override to provide a tooltip // other than the Name property for each item in the view. @@ -94,14 +100,14 @@ class nsIRDFService; - (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren; // Implementation Methods -- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource; +- (id)getWrapperFor:(nsIRDFResource*) aRDFResource; +- (void)invalidateCachedItems; // override to do something different with the cell data rather than just // return a string (add an icon in an attributed string, for example). --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; +- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem; --(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem - result:(PRUnichar**)outResult; +- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem; @end diff --git a/camino/src/extensions/RDFOutlineViewDataSource.mm b/camino/src/extensions/RDFOutlineViewDataSource.mm index 9b5993d91d1..a293b6a23b2 100644 --- a/camino/src/extensions/RDFOutlineViewDataSource.mm +++ b/camino/src/extensions/RDFOutlineViewDataSource.mm @@ -41,6 +41,7 @@ #import "RDFOutlineViewDataSource.h" #import "CHBrowserService.h" +#include "nsCRT.h" #include "nsIRDFDataSource.h" #include "nsIRDFService.h" #include "nsIRDFLiteral.h" @@ -55,14 +56,116 @@ #include "nsXPIDLString.h" #include "nsString.h" -@interface RDFOutlineViewDataSource(Private); -- (void)registerForShutdownNotification; -- (void)cleanup; +@interface RDFOutlineViewItem(Private) + +- (unsigned int)cacheVersion; +- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version; +- (void)setChildren:(NSArray*)childArray; +- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren; +- (BOOL)cachedChildren; + +- (BOOL)isExpandable; +- (int)numChildren; +- (id)childAtIndex:(int)index; @end +@implementation RDFOutlineViewItem + +- (id)init +{ + if ((self = [super init])) + { + mCacheVersion = 0; + mExpandable = NO; + mNumChildren = 0; + } + return self; +} + +- (void)dealloc +{ + [mChildNodes release]; + NS_IF_RELEASE(mResource); + [super dealloc]; +} + +- (nsIRDFResource*)resource +{ + NS_IF_ADDREF(mResource); + return mResource; +} + +- (void)setResource:(nsIRDFResource*) aResource +{ + nsIRDFResource* oldResource = mResource; + NS_IF_ADDREF(mResource = aResource); + NS_IF_RELEASE(oldResource); +} + +- (unsigned int)cacheVersion +{ + return mCacheVersion; +} + +- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version; +{ + mNumChildren = numChildren; + mExpandable = expandable; + mCacheVersion = version; +} + +- (void)setChildren:(NSArray*)childArray +{ + // childArray can legally be nil here. If it is, we're clearing the cached children + NSArray* oldChildren = mChildNodes; + mChildNodes = childArray; + [mChildNodes retain]; + [oldChildren release]; +} + +- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren; +{ + return (mCacheVersion == version) && (needChildren ? (mChildNodes != nil) : 1); +} + +- (BOOL)cachedChildren +{ + return (mChildNodes != nil); +} + +- (BOOL)isExpandable +{ + return mExpandable; +} + +- (int)numChildren +{ + return mNumChildren; +} + +- (id)childAtIndex:(int)index +{ + if (mChildNodes) + return [mChildNodes objectAtIndex:index]; + + return nil; +} + +@end + +#pragma mark - + +@interface RDFOutlineViewDataSource(Private) + +- (void)registerForShutdownNotification; +- (void)cleanup; +- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren; + +@end + @implementation RDFOutlineViewDataSource - (id)init @@ -70,6 +173,7 @@ if ((self = [super init])) { [self registerForShutdownNotification]; + mCacheVersion = 1; } return self; } @@ -78,7 +182,7 @@ { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self cleanup]; + [self cleanup]; [super dealloc]; } @@ -167,123 +271,62 @@ // XXX - For now, we'll just say that none of our items are editable, as we aren't using any // RDF datasources that are mutable. // -- (BOOL) outlineView: (NSOutlineView*) aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn +- (BOOL) outlineView: (NSOutlineView*)aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn item: (id) aItem { - return NO; + return NO; } -- (BOOL) outlineView: (NSOutlineView*) aOutlineView isItemExpandable: (id) aItem +- (BOOL) outlineView: (NSOutlineView*)aOutlineView isItemExpandable:(id)aItem { - if (!mDataSource) - return NO; - - if (!aItem) - return YES; // The root is always open - - nsCOMPtr itemResource = dont_AddRef([aItem resource]); - - PRBool isSeq = PR_FALSE; - mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq); - if (isSeq) - return YES; - - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNode; - mDataSource->GetTarget(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNode)); - - return childNode != nsnull; + if (!mDataSource) + return NO; + + if (!aItem) + return YES; // The root is always open + + if (![aItem cacheValid:mCacheVersion needChildren:NO]) + [self updateItemProperties:aItem enumerateChildren:NO]; + + return [aItem isExpandable]; } -- (id) outlineView: (NSOutlineView*) aOutlineView child: (int) aIndex - ofItem: (id) aItem +- (id)outlineView:(NSOutlineView*)aOutlineView child:(int)aIndex ofItem:(id)aItem { - if (!mDataSource) - return nil; + if (!mDataSource) + return nil; + + if (!aItem) + { + nsCOMPtr rootResource = dont_AddRef([self rootResource]); + aItem = [self getWrapperFor:rootResource]; + } + + if (![aItem cacheValid:mCacheVersion needChildren:YES]) + [self updateItemProperties:aItem enumerateChildren:YES]; - nsCOMPtr resource = !aItem ? dont_AddRef([self rootResource]) : dont_AddRef([aItem resource]); - - nsCOMPtr ordinalResource; - mContainerUtils->IndexToOrdinalResource(aIndex + 1, getter_AddRefs(ordinalResource)); - - nsCOMPtr childNode; - mDataSource->GetTarget(resource, ordinalResource, PR_TRUE, getter_AddRefs(childNode)); - if (childNode) { - // Yay. A regular container. We don't need to count, we can go directly to - // our object. - nsCOMPtr childResource(do_QueryInterface(childNode)); - if (childResource) - return [self makeWrapperFor:childResource]; - } - else - { - // Oh well, not a regular container. We need to count, dagnabbit. - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNodes; - mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); - - nsCOMPtr supp; - PRInt32 count = 0; - - PRBool hasMore = PR_FALSE; - while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) - { - childNodes->GetNext(getter_AddRefs(supp)); - if (count == aIndex) - break; - count ++; - } - - nsCOMPtr childResource(do_QueryInterface(supp)); - if (childResource) { - return [self makeWrapperFor:childResource]; - } - } - - return nil; + return [aItem childAtIndex:aIndex]; } -- (int) outlineView: (NSOutlineView*) aOutlineView numberOfChildrenOfItem: (id) aItem; +- (int)outlineView:(NSOutlineView*)aOutlineView numberOfChildrenOfItem:(id) aItem; { - if (!mDataSource) - return 0; - - nsCOMPtr resource = dont_AddRef(aItem ? [aItem resource] : [self rootResource]); - - // XXX just assume NC:child is the only containment arc for now - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNodes; - mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); - - PRBool hasMore = PR_FALSE; - PRInt32 count = 0; - - while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) - { - nsCOMPtr supp; - childNodes->GetNext(getter_AddRefs(supp)); - count ++; - } - - if (count == 0) { - nsresult rv = mContainer->Init(mDataSource, resource); - if (NS_FAILED(rv)) - return 0; - - mContainer->GetCount(&count); - } - - return count; + if (!mDataSource) + return 0; + + if (!aItem) + { + nsCOMPtr rootResource = dont_AddRef([self rootResource]); + aItem = [self getWrapperFor:rootResource]; + } + + if (![aItem cacheValid:mCacheVersion needChildren:YES]) + [self updateItemProperties:aItem enumerateChildren:YES]; + + return [aItem numChildren]; } -- (id) outlineView: (NSOutlineView*) aOutlineView objectValueForTableColumn: (NSTableColumn*) aTableColumn - byItem: (id) aItem +- (id)outlineView:(NSOutlineView*)aOutlineView objectValueForTableColumn:(NSTableColumn*)aTableColumn + byItem:(id)aItem { if (!mDataSource || !aItem) return nil; @@ -291,25 +334,22 @@ // The table column's identifier is the RDF Resource URI of the property being displayed in // that column, e.g. "http://home.netscape.com/NC-rdf#Name" NSString* columnPropertyURI = [aTableColumn identifier]; - nsXPIDLString literalValue; - [self getPropertyString:columnPropertyURI forItem:aItem result:getter_Copies(literalValue)]; + NSString* propString = [self getPropertyString:columnPropertyURI forItem:aItem]; - return [self createCellContents:literalValue withColumn:columnPropertyURI byItem:aItem]; + return [self createCellContents:propString withColumn:columnPropertyURI byItem:aItem]; } - // // createCellContents:withColumn:byItem // // Constructs a NSString from the given string data for this item in the given column. // This should be overridden to do more fancy things, such as add an icon, etc. // --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem +- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem { - return [NSString stringWith_nsAString: inValue]; + return inValue; } - // // outlineView:tooltipForString // @@ -318,21 +358,9 @@ // - (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem { - nsXPIDLString literalValue; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem result:getter_Copies(literalValue)]; - return [NSString stringWith_nsAString:literalValue]; + return [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem]; } - -- (void) outlineView: (NSOutlineView*) aOutlineView setObjectValue: (id) aObject - forTableColumn: (NSTableColumn*) aTableColumn - byItem: (id) aItem -{ - -} - - - - (void) reloadDataForItem: (id) aItem reloadChildren: (BOOL) aReloadChildren { if (!aItem) @@ -341,7 +369,7 @@ [mOutlineView reloadItem: aItem reloadChildren: aReloadChildren]; } -- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource +- (id)getWrapperFor:(nsIRDFResource*) aRDFResource { const char* k; aRDFResource->GetValueConst(&k); @@ -350,8 +378,9 @@ // see if we've created a wrapper already, if not, create a new wrapper object // and stash it in our dictionary RDFOutlineViewItem* item = [mDictionary objectForKey:key]; - if (!item) { - item = [[RDFOutlineViewItem alloc] init]; + if (!item) + { + item = [[[RDFOutlineViewItem alloc] init] autorelease]; [item setResource: aRDFResource]; [mDictionary setObject:item forKey:key]; // retains |item| } @@ -359,14 +388,56 @@ return item; } - --(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem - result:(PRUnichar**)outResult +- (void)invalidateCachedItems { - if ( !outResult ) - return; - *outResult = nil; + mCacheVersion++; +} + +- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren +{ + BOOL isExpandable = NO; + NSMutableArray* itemChildren = doChildren ? [[[NSMutableArray alloc] initWithCapacity:10] autorelease] : nil; + nsCOMPtr itemResource = dont_AddRef([item resource]); + + PRBool isSeq = PR_FALSE; + mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq); + if (isSeq) + isExpandable = YES; + + nsCOMPtr childProperty; + mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); + + nsCOMPtr childNodes; + mDataSource->GetTargets(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); + + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) + { + nsCOMPtr supp; + childNodes->GetNext(getter_AddRefs(supp)); + + nsCOMPtr childResource = do_QueryInterface(supp); + if (childResource) + { + id childItem = [self getWrapperFor:childResource]; + if (childItem) + { + isExpandable = YES; + if (!itemChildren) break; // know enough already + [itemChildren addObject:childItem]; + } + } + } + + // itemChildren will be nil here if we don't care about children, but that's OK. + // the setChildren call will clear the cached child list. + [item setNumChildren:[itemChildren count] isExpandable:isExpandable cacheVersion:mCacheVersion]; + [item setChildren:itemChildren]; +} + +- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem +{ nsCOMPtr propertyResource; mRDFService->GetResource([inPropertyURI UTF8String], getter_AddRefs(propertyResource)); @@ -378,38 +449,20 @@ #if DEBUG NSLog(@"ValueNode is null in RDF objectValueForTableColumn"); #endif - return; + return @""; } nsCOMPtr valueLiteral(do_QueryInterface(valueNode)); if (!valueLiteral) - return; + return @""; - valueLiteral->GetValue(outResult); + const PRUnichar* value = NULL; + valueLiteral->GetValueConst(&value); + if (value) + return [NSString stringWithCharacters:value length:nsCRT::strlen(value)]; + + return @""; } -@end - -@implementation RDFOutlineViewItem - -- (void) dealloc -{ - NS_IF_RELEASE(mResource); - [super dealloc]; -} - -- (nsIRDFResource*) resource -{ - NS_IF_ADDREF(mResource); - return mResource; -} - -- (void) setResource: (nsIRDFResource*) aResource -{ - nsIRDFResource* oldResource = mResource; - NS_IF_ADDREF(mResource = aResource); - NS_IF_RELEASE(oldResource); -} - @end diff --git a/camino/src/history/HistoryDataSource.h b/camino/src/history/HistoryDataSource.h index ac3e29f437b..1fb186b4922 100644 --- a/camino/src/history/HistoryDataSource.h +++ b/camino/src/history/HistoryDataSource.h @@ -49,17 +49,23 @@ class HistoryDataSourceObserver; { HistoryDataSourceObserver* mObserver; // STRONG ref, should be nsCOMPtr but can't IBOutlet BrowserWindowController* mBrowserWindowController; + BOOL mUpdatesEnabled; + BOOL mNeedsRefresh; } // overridden to create a attributed string with icon --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; +- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; - (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem; --(void) enableObserver; --(void) disableObserver; +- (void)enableObserver; +- (void)disableObserver; --(IBAction)openHistoryItem: (id)aSender; --(IBAction)deleteHistoryItems: (id)aSender; +- (void)setNeedsRefresh:(BOOL)needsRefresh; +- (BOOL)needsRefresh; +- (void)refresh; + +- (IBAction)openHistoryItem: (id)aSender; +- (IBAction)deleteHistoryItems: (id)aSender; @end diff --git a/camino/src/history/HistoryDataSource.mm b/camino/src/history/HistoryDataSource.mm index f1d040f99df..52a7a4bf7c3 100644 --- a/camino/src/history/HistoryDataSource.mm +++ b/camino/src/history/HistoryDataSource.mm @@ -63,33 +63,29 @@ class HistoryDataSourceObserver : public nsIRDFObserver { public: - HistoryDataSourceObserver(NSOutlineView* outlineView) : - mOutlineView(outlineView), mEnabled(false) + HistoryDataSourceObserver(HistoryDataSource* dataSource) + : mHistoryDataSource(dataSource) { NS_INIT_ISUPPORTS(); } - virtual ~HistoryDataSourceObserver() { } ; + virtual ~HistoryDataSourceObserver() { } NS_DECL_ISUPPORTS - NS_IMETHODIMP OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) ; - NS_IMETHODIMP OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) { return NS_OK; } + NS_IMETHOD OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*); + NS_IMETHOD OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*); - NS_IMETHODIMP OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) + NS_IMETHOD OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) { return NS_OK; } - NS_IMETHODIMP OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*); + NS_IMETHOD OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*); - NS_IMETHODIMP BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; } - NS_IMETHODIMP EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; } - - void Enable() { mEnabled = true; } - void Disable() { mEnabled = false; } + NS_IMETHOD BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; } + NS_IMETHOD EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; } private: - NSOutlineView* mOutlineView; - bool mEnabled; + HistoryDataSource* mHistoryDataSource; }; NS_IMPL_ISUPPORTS1(HistoryDataSourceObserver, nsIRDFObserver) @@ -105,15 +101,30 @@ NS_IMETHODIMP HistoryDataSourceObserver::OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource* aProperty, nsIRDFNode*) { - if(mEnabled) { - const char* p; - aProperty->GetValueConst(&p); - if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) - [mOutlineView reloadData]; - } + const char* p; + aProperty->GetValueConst(&p); + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + return NS_OK; } +// +// OnUnassert +// +// This gets called on redirects, when nsGlobalHistory::RemovePage is called. +// +NS_IMETHODIMP +HistoryDataSourceObserver::OnUnassert(nsIRDFDataSource*, nsIRDFResource*, + nsIRDFResource* aProperty, nsIRDFNode*) +{ + const char* p; + aProperty->GetValueConst(&p); + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + + return NS_OK; +} // // OnChange @@ -125,12 +136,12 @@ NS_IMETHODIMP HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource* aProperty, nsIRDFNode*, nsIRDFNode*) { - if(mEnabled) { - const char* p; - aProperty->GetValueConst(&p); - if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) - [mOutlineView reloadData]; - } + const char* p; + aProperty->GetValueConst(&p); + + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + return NS_OK; } @@ -138,7 +149,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, @interface HistoryDataSource(Private) -- (void)cleanup; +- (void)cleanupHistory; @end @@ -146,12 +157,12 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, - (void) dealloc { - [self cleanup]; + [self cleanupHistory]; [super dealloc]; } // "non-virtual" cleanup method -- safe to call from dealloc. -- (void)cleanup +- (void)cleanupHistory { if (mDataSource && mObserver) { @@ -163,7 +174,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, // "virtual" method; called from superclass - (void)cleanupDataSource { - [self cleanup]; + [self cleanupHistory]; [super cleanupDataSource]; } @@ -181,7 +192,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NS_ASSERTION(mRDFService, "Uh oh, RDF service not loaded in parent class"); - if ( !mDataSource ) { + if ( !mDataSource ) + { // Get the Global History DataSource mRDFService->GetDataSource("rdf:history", &mDataSource); // Get the Date Folder Root @@ -191,14 +203,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, [mOutlineView setDoubleAction: @selector(openHistoryItem:)]; [mOutlineView setDeleteAction: @selector(deleteHistoryItems:)]; - mObserver = new HistoryDataSourceObserver(mOutlineView); + mObserver = new HistoryDataSourceObserver(self); if ( mObserver ) { NS_ADDREF(mObserver); mDataSource->AddObserver(mObserver); } [mOutlineView reloadData]; } - else { + else + { // everything is loaded, but we have to refresh our tree otherwise // changes that took place while the drawer was closed won't be noticed [mOutlineView reloadData]; @@ -207,18 +220,41 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NS_ASSERTION(mDataSource, "Uh oh, History RDF Data source not created"); } -- (void) enableObserver +- (void)enableObserver { - if ( mObserver ) - mObserver->Enable(); + mUpdatesEnabled = YES; } --(void) disableObserver +-(void)disableObserver { - if ( mObserver ) - mObserver->Disable(); + mUpdatesEnabled = NO; } +- (void)setNeedsRefresh:(BOOL)needsRefresh +{ + mNeedsRefresh = needsRefresh; +} + +- (BOOL)needsRefresh +{ + return mNeedsRefresh; +} + +- (void)refresh +{ + if (mNeedsRefresh) + { + [self invalidateCachedItems]; + if (mUpdatesEnabled) + { + // this can be very slow! See bug 180109. + //NSLog(@"history reload started"); + [self reloadDataForItem:nil reloadChildren:NO]; + //NSLog(@"history reload done"); + } + mNeedsRefresh = NO; + } +} // // createCellContents:withColumn:byItem @@ -226,31 +262,29 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, // override to create an NSAttributedString instead of just the string with the // given text. We add an icon and adjust the positioning of the text w/in the cell // --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem +-(id) createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem { - NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init]; - - //Set cell's textual contents - [cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString:inValue]]; + if ([inValue length] == 0) + inValue = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem]; - if ([inColumn isEqualToString: @"http://home.netscape.com/NC-rdf#Name"]) { - NSMutableAttributedString *attachmentAttrString = nil; - NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - NSCell *attachmentAttrStringCell; + NSMutableAttributedString *cellValue = [[[NSMutableAttributedString alloc] initWithString:inValue] autorelease]; + + if ([inColumn isEqualToString:@"http://home.netscape.com/NC-rdf#Name"]) + { + NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; + NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - //Create an attributed string to hold the empty attachment, then release the components. - attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain]; + // Create an attributed string to hold the empty attachment, then release the components. + NSMutableAttributedString *attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; [textAttachment release]; [fileWrapper release]; //Get the cell of the text attachment. - attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute: + NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute: NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell]; - if ([self outlineView:mOutlineView isItemExpandable:inItem]) { + if ([self outlineView:mOutlineView isItemExpandable:inItem]) [attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]]; - } else [attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]]; @@ -298,11 +332,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, id item = [toDrag objectAtIndex: 0]; // if we have just one item, we add some more flavours - nsXPIDLString urlLiteral, nameLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item result:getter_Copies(nameLiteral)]; - NSString* url = [NSString stringWith_nsAString: urlLiteral]; - NSString* title = [NSString stringWith_nsAString: nameLiteral]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; + NSString* title = [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item]; NSString *cleanedTitle = [title stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "]; [pboard declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:self]; @@ -340,11 +371,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, return; } - nsXPIDLString urlLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - // get uri - NSString* url = [NSString stringWith_nsAString: urlLiteral]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; [[mBrowserWindowController getBrowserWrapper] loadURI: url referrer: nil flags: NSLoadFlagsNone activate:YES]; } @@ -376,14 +404,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, index = [currIndex intValue]; RDFOutlineViewItem* item = [mOutlineView itemAtRow: index]; if (![mOutlineView isExpandable: item]) { - nsXPIDLString urlLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - history->RemovePage(NS_ConvertUCS2toUTF8(urlLiteral).get()); + NSString* urlString = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; + history->RemovePage([urlString UTF8String]); } } history->EndBatchUpdate(); if ( clearSelectionWhenDone ) [mOutlineView deselectAll:self]; + + [self invalidateCachedItems]; [mOutlineView reloadData]; // necessary or the outline is really horked } } @@ -402,9 +431,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NSString* pageTitle = [super outlineView:outlineView tooltipStringForItem:inItem]; // append url - nsXPIDLString literalValue; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem result:getter_Copies(literalValue)]; - return [NSString stringWithFormat:@"%@\n%@", pageTitle, [NSString stringWith_nsAString:literalValue]]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem]; + return [NSString stringWithFormat:@"%@\n%@", pageTitle, [url stringByTruncatingTo:80 at:kTruncateAtEnd]]; } return nil; } diff --git a/camino/src/includes/ChimeraUIConstants.h b/camino/src/includes/ChimeraUIConstants.h index b96c6e40dd7..1f6045d0ab7 100644 --- a/camino/src/includes/ChimeraUIConstants.h +++ b/camino/src/includes/ChimeraUIConstants.h @@ -52,3 +52,13 @@ const int kDividerTag = 4000; // the tag of the separator after which to insert bookmark items const int kBookmarksDividerTag = -1; + +// Save file dialog +const int kSaveFormatPopupTag = 1000; + +enum +{ + eSaveFormatHTMLComplete = 0, + eSaveFormatHTMLSource, + eSaveFormatPlainText +}; diff --git a/camino/src/preferences/PreferenceManager.h b/camino/src/preferences/PreferenceManager.h index 8273aca7a71..baa09d1b417 100644 --- a/camino/src/preferences/PreferenceManager.h +++ b/camino/src/preferences/PreferenceManager.h @@ -45,6 +45,9 @@ class nsIPref; NSUserDefaults* mDefaults; ICInstance mInternetConfig; nsIPref* mPrefs; + + // proxies notification stuff + CFRunLoopSourceRef mRunLoopSource; } + (PreferenceManager *)sharedInstance; diff --git a/camino/src/preferences/PreferenceManager.mm b/camino/src/preferences/PreferenceManager.mm index 18cf20c5680..8378bd39d82 100644 --- a/camino/src/preferences/PreferenceManager.mm +++ b/camino/src/preferences/PreferenceManager.mm @@ -38,6 +38,7 @@ #import #import + #import "PreferenceManager.h" #import "UserDefaults.h" #import "CHBrowserService.h" @@ -60,11 +61,23 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count); @interface PreferenceManager(PreferenceManagerPrivate) ++ (PreferenceManager *) sharedInstanceDontCreate; + - (void)registerNotificationListener; - (void)termEmbedding: (NSNotification*)aNotification; - (void)xpcomTerminate: (NSNotification*)aNotification; +- (void)configureProxies; +- (BOOL)updateOneProxy:(NSDictionary*)configDict + protocol:(NSString*)protocol + proxyEnableKey:(NSString*)enableKey + proxyURLKey:(NSString*)urlKey + proxyPortKey:(NSString*)portKey; + +- (void)registerForProxyChanges; +- (BOOL)readSystemProxySettings; + @end @@ -76,7 +89,7 @@ static PreferenceManager* gSharedInstance = nil; static BOOL gMadePrefManager; #endif -+ (PreferenceManager *) sharedInstance ++ (PreferenceManager *)sharedInstance { if (!gSharedInstance) { @@ -88,13 +101,20 @@ static BOOL gMadePrefManager; gSharedInstance = [[PreferenceManager alloc] init]; } - return gSharedInstance; + return gSharedInstance; +} + ++ (PreferenceManager *)sharedInstanceDontCreate +{ + return gSharedInstance; } - (id) init { if ((self = [super init])) { + mRunLoopSource = NULL; + [self registerNotificationListener]; if ([self initInternetConfig] == NO) { @@ -115,6 +135,8 @@ static BOOL gMadePrefManager; - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (self == gSharedInstance) + gSharedInstance = nil; [super dealloc]; } @@ -123,6 +145,13 @@ static BOOL gMadePrefManager; ::ICStop(mInternetConfig); mInternetConfig = nil; NS_IF_RELEASE(mPrefs); + // remove our runloop observer + if (mRunLoopSource) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes); + CFRelease(mRunLoopSource); + mRunLoopSource = NULL; + } } - (void)xpcomTerminate: (NSNotification*)aNotification @@ -145,14 +174,14 @@ static BOOL gMadePrefManager; object: nil]; } -- (void) savePrefsFile +- (void)savePrefsFile { nsCOMPtr prefsService = do_GetService(NS_PREF_CONTRACTID); if (prefsService) prefsService->SavePrefFile(nsnull); } -- (BOOL) initInternetConfig +- (BOOL)initInternetConfig { OSStatus error; error = ::ICStart(&mInternetConfig, 'CHIM'); @@ -164,7 +193,7 @@ static BOOL gMadePrefManager; return YES; } -- (BOOL) initMozillaPrefs +- (BOOL)initMozillaPrefs { #ifdef _BUILD_STATIC_BIN @@ -246,15 +275,8 @@ static BOOL gMadePrefManager; return YES; } -- (void) syncMozillaPrefs +- (void)syncMozillaPrefs { - CFArrayRef cfArray; - CFDictionaryRef cfDictionary; - CFNumberRef cfNumber; - CFStringRef cfString; - char strbuf[1024]; - int numbuf; - if (!mPrefs) { NSLog(@"Mozilla prefs not set up successfully"); return; @@ -268,19 +290,101 @@ static BOOL gMadePrefManager; // fix up the cookie prefs. If 'p3p' or 'accept foreign cookies' are on, remap them to // something that chimera can deal with. PRInt32 acceptCookies = 0; - static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior"; + static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior"; mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies); - if ( acceptCookies == 1 ) { // accept foreign cookies, assume off + if ( acceptCookies == 1 ) { // accept foreign cookies, assume off acceptCookies = 2; - mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); - } + mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); + } else if ( acceptCookies == 3 ) { // p3p, assume all cookies on acceptCookies = 0; - mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); + mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); } - + + [self configureProxies]; +} + +#pragma mark - + +- (void)configureProxies +{ + [self readSystemProxySettings]; + [self registerForProxyChanges]; +} + +static void SCProxiesChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void * /* info */) +{ + PreferenceManager* prefsManager = [PreferenceManager sharedInstanceDontCreate]; + [prefsManager readSystemProxySettings]; +#if DEBUG + NSLog(@"Updating proxies"); +#endif +} + +- (void)registerForProxyChanges +{ + if (mRunLoopSource) // don't register twice + return; + + SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; + + SCDynamicStoreRef dynamicStoreRef = SCDynamicStoreCreate(NULL, CFSTR("ChimeraProxiesNotification"), SCProxiesChangedCallback, &context); + if (dynamicStoreRef) + { + CFStringRef proxyIdentifier = SCDynamicStoreKeyCreateProxies(NULL); + CFArrayRef keyList = CFArrayCreate(NULL, (const void **)&proxyIdentifier, 1, &kCFTypeArrayCallBacks); + + Boolean set = SCDynamicStoreSetNotificationKeys(dynamicStoreRef, keyList, NULL); + if (set) + { + mRunLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, dynamicStoreRef, 0); + if (mRunLoopSource) + { + CFRunLoopAddSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes); + // we keep the ref to the source, so that we can remove it when the prefs manager is cleaned up. + } + } + + CFRelease(proxyIdentifier); + CFRelease(keyList); + CFRelease(dynamicStoreRef); + } +} + +- (BOOL)updateOneProxy:(NSDictionary*)configDict + protocol:(NSString*)protocol + proxyEnableKey:(NSString*)enableKey + proxyURLKey:(NSString*)urlKey + proxyPortKey:(NSString*)portKey +{ + BOOL gotProxy = NO; + + BOOL enabled = (BOOL)[[configDict objectForKey:enableKey] intValue]; + if (enabled) + { + NSString* protocolProxy = [configDict objectForKey:urlKey]; + int proxyPort = [[configDict objectForKey:portKey] intValue]; + if ([protocolProxy length] > 0 && proxyPort != 0) + { + [self setPref:[[NSString stringWithFormat:@"network.proxy.%@", protocol] cString] toString:protocolProxy]; + [self setPref:[[NSString stringWithFormat:@"network.proxy.%@_port", protocol] cString] toInt:proxyPort]; + gotProxy = YES; + } + } + + return gotProxy; +} + +- (BOOL)readSystemProxySettings +{ + BOOL usingProxies = NO; + + PRInt32 proxyType, newProxyType; + mPrefs->GetIntPref("network.proxy.type", &proxyType); + newProxyType = proxyType; + if (proxyType == 0 || proxyType == 1) + { // get proxies from SystemConfiguration - mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies mPrefs->ClearUserPref("network.proxy.http"); mPrefs->ClearUserPref("network.proxy.http_port"); mPrefs->ClearUserPref("network.proxy.ssl"); @@ -293,94 +397,66 @@ static BOOL gMadePrefManager; mPrefs->ClearUserPref("network.proxy.socks_port"); mPrefs->ClearUserPref("network.proxy.no_proxies_on"); - if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.http", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.http_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } + NSDictionary* proxyConfigDict = (NSDictionary*)SCDynamicStoreCopyProxies(NULL); + if (proxyConfigDict) + { + BOOL gotAProxy = NO; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"http" + proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPEnable + proxyURLKey:(NSString*)kSCPropNetProxiesHTTPProxy + proxyPortKey:(NSString*)kSCPropNetProxiesHTTPPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ssl" + proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPSEnable + proxyURLKey:(NSString*)kSCPropNetProxiesHTTPSProxy + proxyPortKey:(NSString*)kSCPropNetProxiesHTTPSPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ftp" + proxyEnableKey:(NSString*)kSCPropNetProxiesFTPEnable + proxyURLKey:(NSString*)kSCPropNetProxiesFTPProxy + proxyPortKey:(NSString*)kSCPropNetProxiesFTPPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"gopher" + proxyEnableKey:(NSString*)kSCPropNetProxiesGopherEnable + proxyURLKey:(NSString*)kSCPropNetProxiesGopherProxy + proxyPortKey:(NSString*)kSCPropNetProxiesGopherPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"socks" + proxyEnableKey:(NSString*)kSCPropNetProxiesSOCKSEnable + proxyURLKey:(NSString*)kSCPropNetProxiesSOCKSProxy + proxyPortKey:(NSString*)kSCPropNetProxiesSOCKSPort]; + + if (gotAProxy) + { + newProxyType = 1; + + NSArray* exceptions = [proxyConfigDict objectForKey:(NSString*)kSCPropNetProxiesExceptionsList]; + if (exceptions) + { + NSString* sitesList = [exceptions componentsJoinedByString:@", "]; + if ([sitesList length] > 0) + [self setPref:"network.proxy.no_proxies_on" toString:sitesList]; } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.ssl", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.ssl_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.ftp", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.ftp_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.gopher", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.gopher_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.socks", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.socks_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesExceptionsList, (const void **)&cfArray) == TRUE) { - cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", ")); - if (CFStringGetLength (cfString) > 0) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf); - } - } - } - CFRelease (cfDictionary); + usingProxies = YES; + } + else + { + newProxyType = 0; + } + + [proxyConfigDict release]; } + + if (newProxyType != proxyType) + mPrefs->SetIntPref("network.proxy.type", 1); + } + + return usingProxies; } +#pragma mark - + - (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess { NSString *prefValue = @""; @@ -406,16 +482,16 @@ static BOOL gMadePrefManager; { // colors are stored in HTML-like #FFFFFF strings NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess]; - NSColor* returnColor = [NSColor blackColor]; + NSColor* returnColor = [NSColor blackColor]; if ([colorString hasPrefix:@"#"] && [colorString length] == 7) { unsigned int redInt, greenInt, blueInt; sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt); - float redFloat = ((float)redInt / 255.0); - float greenFloat = ((float)greenInt / 255.0); - float blueFloat = ((float)blueInt / 255.0); + float redFloat = ((float)redInt / 255.0); + float greenFloat = ((float)greenInt / 255.0); + float blueFloat = ((float)blueInt / 255.0); returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f]; } @@ -548,7 +624,7 @@ static BOOL gMadePrefManager; mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]); } else { - homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL]; + homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL]; } if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"]) diff --git a/chimera/Chimera.pbproj/project.pbxproj b/chimera/Chimera.pbproj/project.pbxproj index f789e40d443..7d26c0177ce 100644 --- a/chimera/Chimera.pbproj/project.pbxproj +++ b/chimera/Chimera.pbproj/project.pbxproj @@ -146,6 +146,7 @@ 4A9504CDFFE6A4B311CA0CBA, F593CA5E034EB88E01A967F3, ); + hasScannedForEncodings = 1; isa = PBXProject; knownRegions = ( English, @@ -200,6 +201,7 @@ refType = 4; }; 29B97316FDCFA39411CA2CEA = { + fileEncoding = 30; isa = PBXFileReference; name = main.m; path = src/application/main.m; @@ -495,7 +497,6 @@ "; - shouldUseHeadermap = 1; }; 29B97327FDCFA39411CA2CEA = { buildActionMask = 2147483647; @@ -541,7 +542,6 @@ F55C4DD402D2864E0130B065, F50D9DE402ECC2C601BB4219, F50D9DEF02EE0AB101BB4219, - F50D9DF302EE194001BB4219, F50D9DF702EE2B9B01BB4219, F5D33CBF02EF61AA01A967F3, F566BD1402EFA9AD01A967F3, @@ -565,6 +565,9 @@ F57BEDA003A1825001A9666E, F5C8D55303A2A42401A8016F, F5C8D55603A2A43301A8016F, + A7AEBEC603CB962500A967F8, + A7AEBEE003CB9CD700A967F8, + A7AEBEE903CB9DFB00A967F8, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -643,6 +646,12 @@ F5566DC5038E075F01A80166, F5566DC6038E075F01A80166, F5566DC7038E075F01A80166, + A7AEBED103CB9BD000A967F8, + A7AEBED203CB9BD000A967F8, + A7AEBED303CB9BD000A967F8, + A7AEBEDB03CB9C2F00A967F8, + A7AEBEDC03CB9C2F00A967F8, + A7F01A4903CBBCA500A967F8, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -689,7 +698,6 @@ F59236C302C89ACA0100012B, F50D9DE502ECC2C601BB4219, F50D9DF002EE0AB101BB4219, - F50D9DF402EE194001BB4219, F50D9DF802EE2B9B01BB4219, F5D33CC002EF61AA01A967F3, F5D33CC102EF61AA01A967F3, @@ -712,6 +720,9 @@ F55EBC9D0383665201A80166, F57BED9803A1824001A9666E, F57BED9F03A1825001A9666E, + A7AEBEC903CB964000A967F8, + A7AEBEE303CB9CEC00A967F8, + A7AEBEE603CB9DDF00A967F8, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -752,12 +763,14 @@ //2E3 //2E4 2E2939FF027F33604B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = PageProxyIcon.mm; path = src/browser/PageProxyIcon.mm; refType = 2; }; 2E293A00027F33604B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = PageProxyIcon.h; path = src/browser/PageProxyIcon.h; @@ -776,12 +789,14 @@ }; }; 2E748B72029A448D4B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = GoMenu.h; path = src/browser/GoMenu.h; refType = 2; }; 2E748B73029A448D4B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = GoMenu.mm; path = src/browser/GoMenu.mm; @@ -800,12 +815,14 @@ }; }; 2EEC3E61028138714B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksOutlineView.h; path = src/bookmarks/BookmarksOutlineView.h; refType = 2; }; 2EEC3E62028138714B000102 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksOutlineView.mm; path = src/bookmarks/BookmarksOutlineView.mm; @@ -881,6 +898,292 @@ //982 //983 //984 +//A70 +//A71 +//A72 +//A73 +//A74 + A7AEBEB103CB950400A967F8 = { + isa = PBXFileReference; + name = xmlextras.xpt; + path = ../dist/Embed/components/xmlextras.xpt; + refType = 2; + }; + A7AEBEB303CB954500A967F8 = { + fileRef = A7AEBEB103CB950400A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEB403CB955700A967F8 = { + fileRef = A7AEBEB103CB950400A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC403CB962500A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = "NSView+Utils.h"; + path = "src/extensions/NSView+Utils.h"; + refType = 2; + }; + A7AEBEC503CB962500A967F8 = { + fileRef = A7AEBEC403CB962500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC603CB962500A967F8 = { + fileRef = A7AEBEC403CB962500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC703CB964000A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = "NSView+Utils.m"; + path = "src/extensions/NSView+Utils.m"; + refType = 2; + }; + A7AEBEC803CB964000A967F8 = { + fileRef = A7AEBEC703CB964000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEC903CB964000A967F8 = { + fileRef = A7AEBEC703CB964000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECA03CB96D600A967F8 = { + isa = PBXFileReference; + name = nsProxyAutoConfig.js; + path = ../netwerk/base/src/nsProxyAutoConfig.js; + refType = 2; + }; + A7AEBECB03CB96E700A967F8 = { + fileRef = A7AEBECA03CB96D600A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECC03CB96F900A967F8 = { + fileRef = A7AEBECA03CB96D600A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBECE03CB9BD000A967F8 = { + isa = PBXFileReference; + name = disclosureArrowDown.tiff; + path = resources/images/app/disclosureArrowDown.tiff; + refType = 2; + }; + A7AEBECF03CB9BD000A967F8 = { + isa = PBXFileReference; + name = disclosureArrowRight.tiff; + path = resources/images/app/disclosureArrowRight.tiff; + refType = 2; + }; + A7AEBED003CB9BD000A967F8 = { + isa = PBXFileReference; + name = small_close.tiff; + path = resources/images/app/small_close.tiff; + refType = 2; + }; + A7AEBED103CB9BD000A967F8 = { + fileRef = A7AEBECE03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED203CB9BD000A967F8 = { + fileRef = A7AEBECF03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED303CB9BD000A967F8 = { + fileRef = A7AEBED003CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED403CB9BD000A967F8 = { + fileRef = A7AEBECE03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED503CB9BD000A967F8 = { + fileRef = A7AEBECF03CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED603CB9BD000A967F8 = { + fileRef = A7AEBED003CB9BD000A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBED703CB9C2F00A967F8 = { + children = ( + A7AEBED803CB9C2F00A967F8, + ); + isa = PBXVariantGroup; + name = Keychain.nib; + path = ""; + refType = 2; + }; + A7AEBED803CB9C2F00A967F8 = { + isa = PBXFileReference; + name = English; + path = resources/localized/English.lproj/Keychain.nib; + refType = 4; + }; + A7AEBED903CB9C2F00A967F8 = { + children = ( + A7AEBEDA03CB9C2F00A967F8, + ); + isa = PBXVariantGroup; + name = ProgressView.nib; + path = ""; + refType = 2; + }; + A7AEBEDA03CB9C2F00A967F8 = { + isa = PBXFileReference; + name = English; + path = resources/localized/English.lproj/ProgressView.nib; + refType = 4; + }; + A7AEBEDB03CB9C2F00A967F8 = { + fileRef = A7AEBED703CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDC03CB9C2F00A967F8 = { + fileRef = A7AEBED903CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDD03CB9C2F00A967F8 = { + fileRef = A7AEBED703CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDE03CB9C2F00A967F8 = { + fileRef = A7AEBED903CB9C2F00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEDF03CB9CD700A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = CHStackView.h; + path = src/extensions/CHStackView.h; + refType = 2; + }; + A7AEBEE003CB9CD700A967F8 = { + fileRef = A7AEBEDF03CB9CD700A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE103CB9CD700A967F8 = { + fileRef = A7AEBEDF03CB9CD700A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE203CB9CEC00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = CHStackView.m; + path = src/extensions/CHStackView.m; + refType = 2; + }; + A7AEBEE303CB9CEC00A967F8 = { + fileRef = A7AEBEE203CB9CEC00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE403CB9CEC00A967F8 = { + fileRef = A7AEBEE203CB9CEC00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE503CB9DDF00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ProgressViewController.mm; + path = src/download/ProgressViewController.mm; + refType = 2; + }; + A7AEBEE603CB9DDF00A967F8 = { + fileRef = A7AEBEE503CB9DDF00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE703CB9DDF00A967F8 = { + fileRef = A7AEBEE503CB9DDF00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEE803CB9DFB00A967F8 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ProgressViewController.h; + path = src/download/ProgressViewController.h; + refType = 2; + }; + A7AEBEE903CB9DFB00A967F8 = { + fileRef = A7AEBEE803CB9DFB00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7AEBEEA03CB9DFB00A967F8 = { + fileRef = A7AEBEE803CB9DFB00A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7F01A4803CBBCA500A967F8 = { + isa = PBXBundleReference; + name = PrintPDE.plugin; + path = ../dist/PrintPDE.plugin; + refType = 2; + }; + A7F01A4903CBBCA500A967F8 = { + fileRef = A7F01A4803CBBCA500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; + A7F01A4A03CBBCA500A967F8 = { + fileRef = A7F01A4803CBBCA500A967F8; + isa = PBXBuildFile; + settings = { + }; + }; +//A70 +//A71 +//A72 +//A73 +//A74 //F50 //F51 //F52 @@ -1169,6 +1472,7 @@ }; }; F507BA480213AD5F01D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksService.h; path = src/bookmarks/BookmarksService.h; @@ -1181,6 +1485,7 @@ }; }; F507BA4C0213AFF701D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksService.mm; path = src/bookmarks/BookmarksService.mm; @@ -1224,6 +1529,7 @@ refType = 4; }; F507BA540213C29E01D93544 = { + fileEncoding = 30; isa = PBXFileReference; name = bookmarks.xml; path = resources/application/bookmarks.xml; @@ -1243,18 +1549,23 @@ F540BD1C029ED17901026D5D, F5A112C902DF270F01026D5D, F55B6BF402EF1F7E01026D5D, + A7AEBECE03CB9BD000A967F8, + A7AEBECF03CB9BD000A967F8, + A7AEBED003CB9BD000A967F8, ); isa = PBXGroup; - name = Graphics; + name = images; refType = 4; }; F50D9DE202ECC2C601BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = nsDownloadListener.h; path = src/download/nsDownloadListener.h; refType = 2; }; F50D9DE302ECC2C601BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = nsDownloadListener.mm; path = src/download/nsDownloadListener.mm; @@ -1301,12 +1612,14 @@ }; }; F50D9DED02EE0AB101BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = CHDownloadProgressDisplay.h; path = src/embedding/CHDownloadProgressDisplay.h; refType = 2; }; F50D9DEE02EE0AB101BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = CHDownloadProgressDisplay.mm; path = src/embedding/CHDownloadProgressDisplay.mm; @@ -1324,37 +1637,15 @@ settings = { }; }; - F50D9DF102EE194001BB4219 = { - isa = PBXFileReference; - name = CHDownloadFactories.h; - path = src/embedding/CHDownloadFactories.h; - refType = 2; - }; - F50D9DF202EE194001BB4219 = { - isa = PBXFileReference; - name = CHDownloadFactories.mm; - path = src/embedding/CHDownloadFactories.mm; - refType = 2; - }; - F50D9DF302EE194001BB4219 = { - fileRef = F50D9DF102EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; - F50D9DF402EE194001BB4219 = { - fileRef = F50D9DF202EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F50D9DF502EE2B9A01BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = SaveHeaderSniffer.h; path = src/download/SaveHeaderSniffer.h; refType = 2; }; F50D9DF602EE2B9A01BB4219 = { + fileEncoding = 30; isa = PBXFileReference; name = SaveHeaderSniffer.mm; path = src/download/SaveHeaderSniffer.mm; @@ -1374,8 +1665,6 @@ }; F50D9DF902EE2C1D01BB4219 = { children = ( - F50D9DF102EE194001BB4219, - F50D9DF202EE194001BB4219, F50D9DED02EE0AB101BB4219, F50D9DEE02EE0AB101BB4219, ); @@ -1387,8 +1676,9 @@ children = ( F50D9DF502EE2B9A01BB4219, F50D9DF602EE2B9A01BB4219, - F517395B020CE3740189DA0C, F50D9DE302ECC2C601BB4219, + A7AEBEE503CB9DDF00A967F8, + F517395B020CE3740189DA0C, ); isa = PBXGroup; name = Chimera; @@ -1549,6 +1839,7 @@ }; }; F5125A110202064D01FAFD9F = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWrapper.h; path = src/browser/BrowserWrapper.h; @@ -1682,6 +1973,7 @@ }; }; F5137A1102676B9101026D05 = { + fileEncoding = 30; isa = PBXFileReference; name = Find.h; path = src/find/Find.h; @@ -1768,7 +2060,6 @@ "; - shouldUseHeadermap = 0; }; F51704D3034A305B01026D5D = { buildActionMask = 2147483647; @@ -1898,12 +2189,14 @@ refType = 2; }; F51704E9034A30DF01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityPane.h; path = PreferencePanes/Security/SecurityPane.h; refType = 2; }; F51704EA034A30DF01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityPane.mm; path = PreferencePanes/Security/SecurityPane.mm; @@ -2037,7 +2330,6 @@ "; - shouldUseHeadermap = 0; }; F51704FE034A38FD01026D5D = { buildActionMask = 2147483647; @@ -2169,12 +2461,14 @@ target = F51704FD034A38FD01026D5D; }; F5170515034A398F01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebFeatures.h; path = PreferencePanes/WebFeatures/WebFeatures.h; refType = 2; }; F5170516034A398F01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebFeatures.mm; path = PreferencePanes/WebFeatures/WebFeatures.mm; @@ -2253,6 +2547,7 @@ refType = 2; }; F5170530034B5E9701026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = English.lproj/Localizable.strings; @@ -2271,12 +2566,14 @@ refType = 2; }; F517395A020CE3740189DA0C = { + fileEncoding = 30; isa = PBXFileReference; name = ProgressDlgController.h; path = src/download/ProgressDlgController.h; refType = 2; }; F517395B020CE3740189DA0C = { + fileEncoding = 30; isa = PBXFileReference; name = ProgressDlgController.mm; path = src/download/ProgressDlgController.mm; @@ -2320,6 +2617,7 @@ }; F51842F30206168101A966FE = { children = ( + F5C8D55203A2A42401A8016F, F5F94B900332532801026D5D, F5DE10E60209DC0601A967DF, F517395A020CE3740189DA0C, @@ -2363,6 +2661,7 @@ F53D36BD037843C201A80166, F58DB2D20381FD3301A9666E, F5C8D55503A2A43301A8016F, + A7AEBEE803CB9DFB00A967F8, ); isa = PBXGroup; name = Headers; @@ -2400,12 +2699,14 @@ }; }; F51B70B6026EC98B01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = GetURLCommand.h; path = src/appleevents/GetURLCommand.h; refType = 2; }; F51B70B7026EC98B01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = GetURLCommand.mm; path = src/appleevents/GetURLCommand.mm; @@ -2747,7 +3048,6 @@ "; - shouldUseHeadermap = 0; }; F52627CF027E976B01000102 = { buildActionMask = 2147483647; @@ -2796,6 +3096,7 @@ runOnlyForDeploymentPostprocessing = 0; }; F52627D4027E982201000102 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = Navigation.h; @@ -2804,6 +3105,7 @@ tabWidth = 2; }; F52627D5027E982201000102 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = Navigation.mm; @@ -2989,6 +3291,7 @@ refType = 2; }; F528E218020FD8400168DE43 = { + fileEncoding = 30; isa = PBXFileReference; name = FindDlgController.h; path = src/find/FindDlgController.h; @@ -3001,6 +3304,7 @@ }; }; F528E21A020FD9620168DE43 = { + fileEncoding = 30; isa = PBXFileReference; name = FindDlgController.mm; path = src/find/FindDlgController.mm; @@ -3013,12 +3317,14 @@ }; }; F529788A0371820B01026DCE = { + fileEncoding = 30; isa = PBXFileReference; name = CHClickListener.h; path = src/embedding/CHClickListener.h; refType = 2; }; F529788B0371820B01026DCE = { + fileEncoding = 30; isa = PBXFileReference; name = CHClickListener.mm; path = src/embedding/CHClickListener.mm; @@ -3049,6 +3355,7 @@ }; }; F52CE65902BFA88701026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = resources/localized/English.lproj/Localizable.strings; @@ -3094,12 +3401,14 @@ }; }; F52D5CCF027A887001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteTextField.h; path = src/browser/AutoCompleteTextField.h; refType = 2; }; F52D5CD0027A887001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteTextField.mm; path = src/browser/AutoCompleteTextField.mm; @@ -3118,12 +3427,14 @@ }; }; F52D5CD3027A88C601A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteDataSource.h; path = src/browser/AutoCompleteDataSource.h; refType = 2; }; F52D5CD4027A88C601A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = AutoCompleteDataSource.mm; path = src/browser/AutoCompleteDataSource.mm; @@ -3142,12 +3453,14 @@ }; }; F52D5CD7027D3D5001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = PreferenceManager.h; path = src/preferences/PreferenceManager.h; refType = 2; }; F52D5CD8027D3D5001A80166 = { + fileEncoding = 30; indentWidth = 2; isa = PBXFileReference; name = PreferenceManager.mm; @@ -3203,24 +3516,28 @@ }; }; F52F87CB027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = HistoryDataSource; path = src/history/HistoryDataSource.h; refType = 2; }; F52F87CC027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = RDFOutlineViewDataSource.h; path = src/extensions/RDFOutlineViewDataSource.h; refType = 2; }; F52F87CD027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = HistoryDataSource.mm; path = src/history/HistoryDataSource.mm; refType = 4; }; F52F87CE027D75C301A80165 = { + fileEncoding = 30; isa = PBXFileReference; name = RDFOutlineViewDataSource.mm; path = src/extensions/RDFOutlineViewDataSource.mm; @@ -3251,6 +3568,7 @@ }; }; F53849040349779901A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = Localizable.strings; path = English.lproj/Localizable.strings; @@ -3343,12 +3661,14 @@ }; }; F53C1CD6032FF3B301A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserContentViews.h; path = src/browser/BrowserContentViews.h; refType = 2; }; F53C1CD7032FF3B301A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserContentViews.mm; path = src/browser/BrowserContentViews.mm; @@ -3379,12 +3699,14 @@ }; }; F53D36BA037843B801A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksMenu.mm; path = src/bookmarks/BookmarksMenu.mm; refType = 2; }; F53D36BD037843C201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksMenu.h; path = src/bookmarks/BookmarksMenu.h; @@ -3397,6 +3719,7 @@ }; }; F53E012902AEE91C01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarkInfoController.h; path = src/bookmarks/BookmarkInfoController.h; @@ -3415,6 +3738,7 @@ }; }; F53E012C02AEE93601A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarkInfoController.mm; path = src/bookmarks/BookmarkInfoController.mm; @@ -3471,54 +3795,63 @@ refType = 2; }; F53F21EC022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencePaneDefaults.plist; path = src/preferences/MVPreferencePaneDefaults.plist; refType = 2; }; F53F21ED022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencePaneGroups.plist; path = src/preferences/MVPreferencePaneGroups.plist; refType = 2; }; F53F21EE022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = English; path = resources/localized/English.lproj/MVPreferencePaneGroups.strings; refType = 2; }; F53F21EF022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesController.h; path = src/preferences/MVPreferencesController.h; refType = 2; }; F53F21F0022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesController.mm; path = src/preferences/MVPreferencesController.mm; refType = 2; }; F53F21F1022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesGroupedIconView.h; path = src/preferences/MVPreferencesGroupedIconView.h; refType = 2; }; F53F21F2022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesGroupedIconView.m; path = src/preferences/MVPreferencesGroupedIconView.m; refType = 2; }; F53F21F3022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesMultipleIconView.h; path = src/preferences/MVPreferencesMultipleIconView.h; refType = 2; }; F53F21F4022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = MVPreferencesMultipleIconView.m; path = src/preferences/MVPreferencesMultipleIconView.m; @@ -3548,11 +3881,13 @@ refType = 4; }; F53F21FF022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; path = PersonalPane.h; refType = 4; }; F53F2200022B7C77010001CA = { + fileEncoding = 30; isa = PBXFileReference; path = PersonalPane.m; refType = 4; @@ -3666,12 +4001,14 @@ }; }; F541495A02711A8301A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHToolbarAdditions.h; path = src/extensions/ToolbarAdditions.h; refType = 2; }; F541495B02711A8301A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHToolbarAdditions.m; path = src/extensions/ToolbarAdditions.m; @@ -3690,12 +4027,14 @@ }; }; F541495E02711B0001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHImageAdditions.h; path = src/extensions/ImageAdditions.h; refType = 2; }; F541495F02711B0001A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = CHImageAdditions.m; path = src/extensions/ImageAdditions.m; @@ -3744,12 +4083,14 @@ }; }; F549ACDE0302DE6001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolTip.mm; path = src/browser/ToolTip.mm; refType = 2; }; F549ACDF0302DE6001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = "NSScreen+Utils.m"; path = "src/extensions/NSScreen+Utils.m"; @@ -3780,6 +4121,7 @@ }; }; F549ACE40302DEBB01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = "NSScreen+Utils.h"; path = "src/extensions/NSScreen+Utils.h"; @@ -3798,6 +4140,7 @@ }; }; F549ACE70302DEF001026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolTip.h; path = src/browser/ToolTip.h; @@ -4064,12 +4407,14 @@ }; }; F558099D02F22168015DF512 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSString+Utils.h"; path = "src/extensions/NSString+Utils.h"; refType = 2; }; F558099E02F22168015DF512 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSString+Utils.mm"; path = "src/extensions/NSString+Utils.mm"; @@ -4094,12 +4439,14 @@ }; }; F5581379030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = RemoteDataProvider.h; path = src/browser/RemoteDataProvider.h; refType = 2; }; F558137A030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = SiteIconProvider.h; path = src/browser/SiteIconProvider.h; @@ -4116,12 +4463,14 @@ refType = 4; }; F558137C030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = RemoteDataProvider.mm; path = src/browser/RemoteDataProvider.mm; refType = 2; }; F558137D030AEF9B0176F207 = { + fileEncoding = 30; isa = PBXFileReference; name = SiteIconProvider.mm; path = src/browser/SiteIconProvider.mm; @@ -4176,12 +4525,14 @@ }; }; F558B1F0030F6E470166970F = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserListener.h; path = src/embedding/CHBrowserListener.h; refType = 2; }; F558B1F1030F6E470166970F = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserListener.mm; path = src/embedding/CHBrowserListener.mm; @@ -4305,6 +4656,7 @@ }; }; F55C4DD302D2864D0130B065 = { + fileEncoding = 30; isa = PBXFileReference; name = UserDefaults.h; path = src/application/UserDefaults.h; @@ -4329,12 +4681,14 @@ }; }; F55EBC9A0383665201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksExport.h; path = src/bookmarks/BookmarksExport.h; refType = 2; }; F55EBC9B0383665201A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksExport.mm; path = src/bookmarks/BookmarksExport.mm; @@ -4365,6 +4719,7 @@ }; }; F5607CB5023944AD01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = GeckoUtils.h; path = src/extensions/GeckoUtils.h; @@ -4434,12 +4789,14 @@ }; }; F5648739023C3857010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = IconTabViewItem.h; path = src/extensions/IconTabViewItem.h; refType = 2; }; F564873A023C3857010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = IconTabViewItem.mm; path = src/extensions/IconTabViewItem.mm; @@ -4464,6 +4821,7 @@ }; }; F56610A1039474CB01A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraVersion.r; path = resources/application/ChimeraVersion.r; @@ -4498,6 +4856,7 @@ F56610A40394767101A9666E = { children = ( F56610BC0394775201A9666E, + A7F01A4803CBBCA500A967F8, ); isa = PBXGroup; name = Plugins; @@ -4544,12 +4903,14 @@ }; }; F566BD1202EFA9AD01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = CocoaPromptService.h; path = src/browser/CocoaPromptService.h; refType = 2; }; F566BD1302EFA9AD01A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = CocoaPromptService.mm; path = src/browser/CocoaPromptService.mm; @@ -4580,6 +4941,7 @@ }; }; F56769FB0208F74A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindowController.mm; path = src/browser/BrowserWindowController.mm; @@ -4598,12 +4960,14 @@ refType = 2; }; F568C3CF023A4A5A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = AboutBox.h; path = src/application/AboutBox.h; refType = 2; }; F568C3D0023A4A5A010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = AboutBox.m; path = src/application/AboutBox.m; @@ -4646,6 +5010,7 @@ }; }; F56F241F02AC6D0401A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = nsStaticComponents.cpp; path = src/application/nsStaticComponents.cpp; @@ -5250,6 +5615,7 @@ target = F5A8CE4702DFF039013CA8EC; }; F56F837202E47CCD01EF35C9 = { + fileEncoding = 30; isa = PBXFileReference; name = RegionNames.strings; path = PreferencePanes/Appearance/English.lproj/RegionNames.strings; @@ -5271,12 +5637,14 @@ }; }; F57074B5026BA85F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksToolbar.h; path = src/bookmarks/BookmarksToolbar.h; refType = 2; }; F57074B6026BA85F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksToolbar.mm; path = src/bookmarks/BookmarksToolbar.mm; @@ -5295,12 +5663,14 @@ }; }; F57074B9026BFD0101A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksButton.h; path = src/bookmarks/BookmarksButton.h; refType = 2; }; F57074BA026BFD0101A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksButton.mm; path = src/bookmarks/BookmarksButton.mm; @@ -5319,12 +5689,14 @@ }; }; F57074BD026D80DF01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = LocationBar.h; path = src/browser/LocationBar.h; refType = 2; }; F57074BE026D80DF01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = LocationBar.mm; path = src/browser/LocationBar.mm; @@ -5354,6 +5726,7 @@ refType = 4; }; F57BED9703A1824001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = NetworkServices.mm; path = src/rendezvous/NetworkServices.mm; @@ -5372,6 +5745,7 @@ }; }; F57BED9A03A1824801A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = NetworkServices.h; path = src/rendezvous/NetworkServices.h; @@ -5390,12 +5764,14 @@ }; }; F57BED9D03A1825001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = DNSUtils.c; path = src/rendezvous/DNSUtils.c; refType = 2; }; F57BED9E03A1825001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = DNSUtils.h; path = src/rendezvous/DNSUtils.h; @@ -5506,7 +5882,6 @@ "; - shouldUseHeadermap = 0; }; F57F205D029997E701000106 = { children = ( @@ -5534,12 +5909,14 @@ refType = 2; }; F57F2060029997E701000106 = { + fileEncoding = 30; isa = PBXFileReference; name = PrivacyPane.h; path = PreferencePanes/Privacy/PrivacyPane.h; refType = 2; }; F57F2061029997E701000106 = { + fileEncoding = 30; isa = PBXFileReference; name = PrivacyPane.mm; path = PreferencePanes/Privacy/PrivacyPane.mm; @@ -5700,12 +6077,14 @@ refType = 4; }; F5807369023A1514010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = SplashScreenWindow.h; path = src/application/SplashScreenWindow.h; refType = 2; }; F580736A023A1514010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = SplashScreenWindow.mm; path = src/application/SplashScreenWindow.mm; @@ -5850,7 +6229,6 @@ "; - shouldUseHeadermap = 0; }; F58581AF022B8D62010001CA = { buildActionMask = 2147483647; @@ -5941,19 +6319,22 @@ F507A84A03116E6E01026D5D, F507A84D03116E7401026D5D, F507A85003116E7901026D5D, - F5C8D55203A2A42401A8016F, + A7AEBED703CB9C2F00A967F8, + A7AEBED903CB9C2F00A967F8, ); isa = PBXGroup; name = Nibs; refType = 4; }; F58DB2D20381FD3301A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = JSConsole.h; path = src/application/JSConsole.h; refType = 2; }; F58DB2D30381FD3301A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = JSConsole.mm; path = src/application/JSConsole.mm; @@ -5984,12 +6365,14 @@ }; }; F59236C002C89AC90100012B = { + fileEncoding = 30; isa = PBXFileReference; name = AppDirServiceProvider.cpp; path = src/application/AppDirServiceProvider.cpp; refType = 2; }; F59236C102C89AC90100012B = { + fileEncoding = 30; isa = PBXFileReference; name = AppDirServiceProvider.h; path = src/application/AppDirServiceProvider.h; @@ -6039,6 +6422,7 @@ refType = 2; }; F5949A47030D58A1014E8430 = { + fileEncoding = 30; isa = PBXFileReference; path = xhtml11.dtd; refType = 4; @@ -6106,6 +6490,7 @@ }; }; F59E9F3D0237E28401A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = ContentClickListener.h; path = src/browser/ContentClickListener.h; @@ -6118,6 +6503,7 @@ }; }; F59E9F3F0237E43401A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = ContentClickListener.mm; path = src/browser/ContentClickListener.mm; @@ -6154,6 +6540,7 @@ }; }; F5A3669302CCFAF601DC3354 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksDataSource.h; path = src/bookmarks/BookmarksDataSource.h; @@ -6176,6 +6563,7 @@ refType = 4; }; F5A3669502CCFAF601DC3354 = { + fileEncoding = 30; isa = PBXFileReference; name = BookmarksDataSource.mm; path = src/bookmarks/BookmarksDataSource.mm; @@ -6542,12 +6930,14 @@ refType = 4; }; F5A8CE4102DFEF4C013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = PreferencePaneBase.h; path = PreferencePanes/Shared/PreferencePaneBase.h; refType = 2; }; F5A8CE4202DFEF4C013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = PreferencePaneBase.mm; path = PreferencePanes/Shared/PreferencePaneBase.mm; @@ -6632,7 +7022,6 @@ "; - shouldUseHeadermap = 0; }; F5A8CE4802DFF039013CA8EC = { buildActionMask = 2147483647; @@ -6698,12 +7087,14 @@ refType = 2; }; F5A8CE4E02DFF167013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = Appearance.h; path = PreferencePanes/Appearance/Appearance.h; refType = 2; }; F5A8CE4F02DFF167013CA8EC = { + fileEncoding = 30; isa = PBXFileReference; name = Appearance.mm; path = PreferencePanes/Appearance/Appearance.mm; @@ -6782,6 +7173,7 @@ }; }; F5AE04B20206A34801A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindowController.h; path = src/browser/BrowserWindowController.h; @@ -6794,6 +7186,7 @@ }; }; F5AE04B60206A37C01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = MainController.h; path = src/application/MainController.h; @@ -6806,6 +7199,7 @@ }; }; F5AE04BA0206A4FE01A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = MainController.mm; path = src/application/MainController.mm; @@ -6818,12 +7212,14 @@ }; }; F5B34B01034A505F01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSPasteboard+Utils.mm"; path = "src/extensions/NSPasteboard+Utils.mm"; refType = 2; }; F5B34B04034A50C901A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSPasteboard+Utils.h"; path = "src/extensions/NSPasteboard+Utils.h"; @@ -6876,10 +7272,12 @@ F5FDF166031AF47301DE816D, F5D98EBC031AC38601A96654, F558099D02F22168015DF512, + A7AEBEC403CB962500A967F8, F549ACE40302DEBB01026D5D, F5B34B04034A50C901A80166, F5648739023C3857010001CA, F5C3AB810270072A01A80166, + A7AEBEDF03CB9CD700A967F8, F541495A02711A8301A80166, F541495E02711B0001A80166, ); @@ -6892,9 +7290,11 @@ F5D98EB9031AC37801A96654, F558099E02F22168015DF512, F549ACDF0302DE6001026D5D, + A7AEBEC703CB964000A967F8, F5B34B01034A505F01A80166, F564873A023C3857010001CA, F5C3AB820270072A01A80166, + A7AEBEE203CB9CEC00A967F8, F541495B02711A8301A80166, F541495F02711B0001A80166, F5FDF167031AF47301DE816D, @@ -6905,12 +7305,14 @@ refType = 4; }; F5B950BC030C83B601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabViewItem.h; path = src/browser/BrowserTabViewItem.h; refType = 2; }; F5B950BD030C83B601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabViewItem.mm; path = src/browser/BrowserTabViewItem.mm; @@ -7184,7 +7586,6 @@ "; - shouldUseHeadermap = 0; }; F5BAAB1A02AC45D301A967F3 = { buildActionMask = 2147483647; @@ -7229,7 +7630,6 @@ F50D9DE702ECC36201BB4219, F50D9DE802ECC36201BB4219, F5E37B0C02EE959601A967F3, - F5E37B0D02EE95E201A967F3, F5E37B0E02EE95E201A967F3, F5E37B0F02EE95E201A967F3, F5D33CC202EF61AA01A967F3, @@ -7254,6 +7654,9 @@ F57BEDA203A1825001A9666E, F5C8D55403A2A42401A8016F, F5C8D55703A2A43301A8016F, + A7AEBEC503CB962500A967F8, + A7AEBEE103CB9CD700A967F8, + A7AEBEEA03CB9DFB00A967F8, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -7343,6 +7746,12 @@ F5566DC9038E075F01A80166, F5566DCA038E075F01A80166, F5566DCB038E075F01A80166, + A7AEBED403CB9BD000A967F8, + A7AEBED503CB9BD000A967F8, + A7AEBED603CB9BD000A967F8, + A7AEBEDD03CB9C2F00A967F8, + A7AEBEDE03CB9C2F00A967F8, + A7F01A4A03CBBCA500A967F8, ); isa = PBXResourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -7389,7 +7798,6 @@ F5A3669B02CCFB7A01DC3354, F5A3669C02CCFB7A01DC3354, F50D9DE902ECC36201BB4219, - F5E37B1002EE95E201A967F3, F5E37B1102EE95E201A967F3, F5E37B1202EE95E201A967F3, F5D33CC302EF61AA01A967F3, @@ -7413,6 +7821,9 @@ F55EBC9F0383665201A80166, F57BED9903A1824001A9666E, F57BEDA103A1825001A9666E, + A7AEBEC803CB964000A967F8, + A7AEBEE403CB9CEC00A967F8, + A7AEBEE703CB9DDF00A967F8, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -8253,6 +8664,8 @@ F5BAAC0402AC693C01A967F3, F5BAAC0502AC693C01A967F3, F5BAAC0702AC693C01A967F3, + A7AEBEB403CB955700A967F8, + A7AEBECB03CB96E700A967F8, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -8994,12 +9407,14 @@ }; }; F5BF71450231B8BC010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabView.h; path = src/browser/BrowserTabView.h; refType = 2; }; F5BF71460231B8BC010001CA = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserTabView.mm; path = src/browser/BrowserTabView.mm; @@ -9048,12 +9463,14 @@ }; }; F5C3AB810270072A01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = ExtendedOutlineView.h; path = src/extensions/ExtendedOutlineView.h; refType = 2; }; F5C3AB820270072A01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = ExtendedOutlineView.mm; path = src/extensions/ExtendedOutlineView.mm; @@ -9072,6 +9489,7 @@ }; }; F5C8D55203A2A42401A8016F = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraUIConstants.h; path = src/includes/ChimeraUIConstants.h; @@ -9090,6 +9508,7 @@ }; }; F5C8D55503A2A43301A8016F = { + fileEncoding = 30; isa = PBXFileReference; name = ChimeraUIConstants.h; path = src/includes/ChimeraUIConstants.h; @@ -9152,6 +9571,7 @@ refType = 4; }; F5D1421902BC88F801A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = "redo-prebinding.sh"; path = "src/scripts/redo-prebinding.sh"; @@ -9164,18 +9584,21 @@ }; }; F5D33CBC02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityDialogs.h; path = src/browser/SecurityDialogs.h; refType = 2; }; F5D33CBD02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = AppComponents.mm; path = src/application/AppComponents.mm; refType = 2; }; F5D33CBE02EF61A901A967F3 = { + fileEncoding = 30; isa = PBXFileReference; name = SecurityDialogs.mm; path = src/browser/SecurityDialogs.mm; @@ -9230,6 +9653,7 @@ }; }; F5D98EB9031AC37801A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSBezierPath+Utils.mm"; path = "src/extensions/NSBezierPath+Utils.mm"; @@ -9248,6 +9672,7 @@ }; }; F5D98EBC031AC38601A96654 = { + fileEncoding = 30; isa = PBXFileReference; name = "NSBezierPath+Utils.h"; path = "src/extensions/NSBezierPath+Utils.h"; @@ -9266,6 +9691,7 @@ }; }; F5DA444A027DD5AA01A80166 = { + fileEncoding = 30; isa = PBXFileReference; name = "installed-chrome.txt"; path = "../dist/Embed/chrome/installed-chrome.txt"; @@ -9326,36 +9752,42 @@ }; }; F5DE10E60209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = nsAlertController.h; path = src/browser/nsAlertController.h; refType = 2; }; F5DE10E70209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserView.h; path = src/embedding/CHBrowserView.h; refType = 2; }; F5DE10E80209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserService.h; path = src/embedding/CHBrowserService.h; refType = 2; }; F5DE10E90209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = nsAlertController.mm; path = src/browser/nsAlertController.mm; refType = 2; }; F5DE10EA0209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserView.mm; path = src/embedding/CHBrowserView.mm; refType = 2; }; F5DE10EB0209DC0601A967DF = { + fileEncoding = 30; isa = PBXFileReference; name = CHBrowserService.mm; path = src/embedding/CHBrowserService.mm; @@ -9403,12 +9835,6 @@ settings = { }; }; - F5E37B0D02EE95E201A967F3 = { - fileRef = F50D9DF102EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F5E37B0E02EE95E201A967F3 = { fileRef = F50D9DED02EE0AB101BB4219; isa = PBXBuildFile; @@ -9421,12 +9847,6 @@ settings = { }; }; - F5E37B1002EE95E201A967F3 = { - fileRef = F50D9DF202EE194001BB4219; - isa = PBXBuildFile; - settings = { - }; - }; F5E37B1102EE95E201A967F3 = { fileRef = F50D9DEE02EE0AB101BB4219; isa = PBXBuildFile; @@ -9506,6 +9926,7 @@ refType = 2; }; F5F190BB02D1F81A01026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = ToolbarDefaults.plist; path = resources/application/ToolbarDefaults.plist; @@ -9524,6 +9945,7 @@ }; }; F5F190BE02D217C201026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = WebsiteDefaults.strings; path = resources/application/WebsiteDefaults.strings; @@ -9569,12 +9991,14 @@ }; }; F5F94B900332532801026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = KeychainService.h; path = src/browser/KeychainService.h; refType = 4; }; F5F94B910332532801026D5D = { + fileEncoding = 30; isa = PBXFileReference; name = KeychainService.mm; path = src/browser/KeychainService.mm; @@ -9633,6 +10057,7 @@ }; }; F5F9FBD902E13767012B5DB7 = { + fileEncoding = 30; isa = PBXFileReference; name = RegionMapping.plist; path = PreferencePanes/Appearance/RegionMapping.plist; @@ -9669,6 +10094,7 @@ }; }; F5FCDD5D03A035E001A9666E = { + fileEncoding = 30; isa = PBXFileReference; name = Localizable.strings; path = English.lproj/Localizable.strings; @@ -9689,12 +10115,14 @@ }; }; F5FDF166031AF47301DE816D = { + fileEncoding = 30; isa = PBXFileReference; name = DraggableImageAndTextCell.h; path = src/extensions/DraggableImageAndTextCell.h; refType = 4; }; F5FDF167031AF47301DE816D = { + fileEncoding = 30; isa = PBXFileReference; name = DraggableImageAndTextCell.mm; path = src/extensions/DraggableImageAndTextCell.mm; @@ -9747,12 +10175,14 @@ //F63 //F64 F632AF8302B9AEBB01000103 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindow.h; path = src/browser/BrowserWindow.h; refType = 2; }; F632AF8402B9AEBB01000103 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWindow.mm; path = src/browser/BrowserWindow.mm; @@ -9771,6 +10201,7 @@ }; }; F6BA6D4E01B2F8A601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = BrowserWrapper.mm; path = src/browser/BrowserWrapper.mm; @@ -9946,6 +10377,8 @@ F517941F027F3F2901A967DF, F53A902202C1127A01A967F3, 98590B3603A8938A45A2FA2A, + A7AEBEB103CB950400A967F8, + A7AEBECA03CB96D600A967F8, ); isa = PBXGroup; name = "Gecko Components"; @@ -10079,6 +10512,8 @@ F6BD64B601B3167601A962F7, F53A902402C1137901A967F3, 98E1988603A8A6F345B32312, + A7AEBEB303CB954500A967F8, + A7AEBECC03CB96F900A967F8, ); isa = PBXCopyFilesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -11091,30 +11526,35 @@ runOnlyForDeploymentPostprocessing = 0; }; F6BD64B801B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = charsetalias.properties; path = ../dist/Embed/res/charsetalias.properties; refType = 2; }; F6BD64B901B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = charsetData.properties; path = ../dist/Embed/res/charsetData.properties; refType = 2; }; F6BD64BA01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = langGroups.properties; path = ../dist/Embed/res/langGroups.properties; refType = 2; }; F6BD64BB01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = language.properties; path = ../dist/Embed/res/language.properties; refType = 2; }; F6BD64BC01B316DA01A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = maccharset.properties; path = ../dist/Embed/res/maccharset.properties; @@ -11167,12 +11607,14 @@ refType = 2; }; F6BD64D301B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = htmlBindings.xml; path = ../dist/Embed/res/builtin/htmlBindings.xml; refType = 2; }; F6BD64D501B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = platformHTMLBindings.xml; path = ../dist/Embed/res/builtin/platformHTMLBindings.xml; @@ -11192,30 +11634,35 @@ refType = 2; }; F6BD64D801B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Latin1.properties; path = ../dist/Embed/res/entityTables/html40Latin1.properties; refType = 2; }; F6BD64D901B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Special.properties; path = ../dist/Embed/res/entityTables/html40Special.properties; refType = 2; }; F6BD64DA01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = html40Symbols.properties; path = ../dist/Embed/res/entityTables/html40Symbols.properties; refType = 2; }; F6BD64DB01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = htmlEntityVersions.properties; path = ../dist/Embed/res/entityTables/htmlEntityVersions.properties; refType = 2; }; F6BD64DC01B3172601A962F7 = { + fileEncoding = 30; isa = PBXFileReference; name = transliterate.properties; path = ../dist/Embed/res/entityTables/transliterate.properties; diff --git a/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib b/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib index 7734e3e1f0e..e69de29bb2d 100644 --- a/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib +++ b/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/info.nib @@ -1,17 +0,0 @@ - - - - - IBDocumentLocation - 646 106 458 263 0 0 1600 1002 - IBEditorPositions - - 214 - 70 395 152 96 0 0 1152 746 - - IBFramework Version - 286.0 - IBSystem Version - 6D52 - - diff --git a/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib b/chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib index d46732370de770898b359b688a589650ae3aae8c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 14811 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 diff --git a/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib b/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib index 7398ee93826..e69de29bb2d 100644 --- a/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib +++ b/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/info.nib @@ -1,27 +0,0 @@ - - - - - IBDocumentLocation - 140 56 522 320 0 0 1280 1002 - IBFramework Version - 286.0 - IBGroupedObjects - - 5 - - 12 - 24 - 56 - - - IBLastGroupID - 8 - IBOpenObjects - - 5 - - IBSystem Version - 6F21 - - diff --git a/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib b/chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib index 88d9df4efe6447297553e3dc3b792a02a09fc079..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 10392 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 diff --git a/chimera/resources/images/app/disclosureArrowDown.tiff b/chimera/resources/images/app/disclosureArrowDown.tiff new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/resources/images/app/disclosureArrowRight.tiff b/chimera/resources/images/app/disclosureArrowRight.tiff new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/resources/images/app/small_close.tiff b/chimera/resources/images/app/small_close.tiff new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/resources/localized/English.lproj/BrowserWindow.nib/classes.nib b/chimera/resources/localized/English.lproj/BrowserWindow.nib/classes.nib index 8d9ef756813..e69de29bb2d 100644 --- a/chimera/resources/localized/English.lproj/BrowserWindow.nib/classes.nib +++ b/chimera/resources/localized/English.lproj/BrowserWindow.nib/classes.nib @@ -1,177 +0,0 @@ -{ - IBClasses = ( - {CLASS = AutoCompleteDataSource; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - { - ACTIONS = {onBlur = id; onResize = id; }; - CLASS = AutoCompleteTextField; - LANGUAGE = ObjC; - OUTLETS = {mProxyIcon = PageProxyIcon; }; - SUPERCLASS = NSTextField; - }, - {CLASS = BookmarkItem; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - { - ACTIONS = { - addBookmark = id; - addFolder = id; - deleteBookmarks = id; - openBookmarkInNewTab = id; - openBookmarkInNewWindow = id; - showBookmarkInfo = id; - }; - CLASS = BookmarksDataSource; - LANGUAGE = ObjC; - OUTLETS = { - mBrowserWindowController = id; - mDeleteBookmarkButton = id; - mEditBookmarkButton = id; - mOutlineView = id; - }; - SUPERCLASS = NSObject; - }, - { - CLASS = BookmarksOutlineView; - LANGUAGE = ObjC; - SUPERCLASS = ExtendedOutlineView; - }, - { - ACTIONS = {addFolder = id; }; - CLASS = BookmarksToolbar; - LANGUAGE = ObjC; - SUPERCLASS = NSView; - }, - {CLASS = BrowserContainerView; LANGUAGE = ObjC; SUPERCLASS = NSView; }, - { - CLASS = BrowserContentView; - LANGUAGE = ObjC; - OUTLETS = { - mBookmarksToolbar = BookmarksToolbar; - mBrowserContainerView = NSView; - mStatusBar = NSView; - }; - SUPERCLASS = NSView; - }, - {CLASS = BrowserTabView; LANGUAGE = ObjC; SUPERCLASS = NSTabView; }, - { - CLASS = BrowserWindow; - LANGUAGE = ObjC; - OUTLETS = {mAutoCompleteTextField = id; }; - SUPERCLASS = NSWindow; - }, - { - ACTIONS = { - back = id; - biggerTextSize = id; - bookmarkLink = id; - bookmarkPage = id; - cancelAddBookmarkSheet = id; - cancelLocationSheet = id; - closeCurrentTab = id; - closeOtherTabs = id; - closeSendersTab = id; - copyImageLocation = id; - copyLinkLocation = id; - endAddBookmarkSheet = id; - endLocationSheet = id; - forward = id; - frameToNewTab = id; - frameToNewWindow = id; - frameToThisWindow = id; - getInfo = id; - goToLocationFromToolbarURLField = id; - home = id; - manageBookmarks = id; - moveTabToNewWindow = id; - newTab = id; - nextTab = id; - openLinkInNewTab = id; - openLinkInNewWindow = id; - pageSetup = id; - performSearch = id; - previousTab = id; - printDocument = id; - reload = id; - reloadSendersTab = id; - saveFrameAs = id; - saveImageAs = id; - saveLinkAs = id; - savePageAs = id; - sendURL = id; - smallerTextSize = id; - stop = id; - toggleSidebar = id; - viewOnlyThisImage = id; - viewPageSource = id; - viewSource = id; - }; - CLASS = BrowserWindowController; - LANGUAGE = ObjC; - OUTLETS = { - mAddBookmarkCheckbox = NSButton; - mAddBookmarkFolderField = NSPopUpButton; - mAddBookmarkSheetWindow = NSWindow; - mAddBookmarkTitleField = NSTextField; - mBackItem = NSMenuItem; - mContentView = BrowserContentView; - mCopyItem = NSMenuItem; - mForwardItem = NSMenuItem; - mHistoryDataSource = HistoryDataSource; - mImageLinkMenu = NSMenu; - mImageMenu = NSMenu; - mInputMenu = NSMenu; - mLinkMenu = NSMenu; - mLocationSheetURLField = NSTextField; - mLocationSheetWindow = NSWindow; - mLocationToolbarView = NSView; - mLock = NSImageView; - mPageMenu = NSMenu; - mPersonalToolbar = BookmarksToolbar; - mProgress = NSProgressIndicator; - mProxyIcon = PageProxyIcon; - mSidebarBookmarksDataSource = BookmarksDataSource; - mSidebarDrawer = NSDrawer; - mSidebarSourceTabView = NSTabView; - mSidebarTabView = NSTabView; - mStatus = NSTextField; - mStatusBar = NSView; - mTabBrowser = BrowserTabView; - mTabMenu = NSMenu; - mURLBar = NSTextField; - }; - SUPERCLASS = NSWindowController; - }, - { - ACTIONS = {load = id; }; - CLASS = BrowserWrapper; - LANGUAGE = ObjC; - OUTLETS = { - mLockIcon = id; - mWindowController = id; - progress = id; - progressSuper = id; - status = id; - urlbar = id; - }; - SUPERCLASS = NSView; - }, - {CLASS = ExtendedOutlineView; LANGUAGE = ObjC; SUPERCLASS = NSOutlineView; }, - {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - { - CLASS = HistoryDataSource; - LANGUAGE = ObjC; - OUTLETS = {mBrowserWindowController = id; }; - SUPERCLASS = RDFOutlineViewDataSource; - }, - {CLASS = LocationBar; LANGUAGE = ObjC; SUPERCLASS = NSView; }, - {CLASS = MainController; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - {CLASS = PageProxyIcon; LANGUAGE = ObjC; SUPERCLASS = NSImageView; }, - { - CLASS = RDFOutlineViewDataSource; - LANGUAGE = ObjC; - OUTLETS = {mOutlineView = id; }; - SUPERCLASS = NSObject; - }, - {CLASS = RDFOutlineViewItem; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, - {CLASS = ThrobberHandler; LANGUAGE = ObjC; SUPERCLASS = NSObject; } - ); - IBVersion = 1; -} \ No newline at end of file diff --git a/chimera/resources/localized/English.lproj/BrowserWindow.nib/info.nib b/chimera/resources/localized/English.lproj/BrowserWindow.nib/info.nib index ae6ff6280c5..2647aded841 100644 --- a/chimera/resources/localized/English.lproj/BrowserWindow.nib/info.nib +++ b/chimera/resources/localized/English.lproj/BrowserWindow.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 66 21 653 383 0 0 1152 848 + 65 36 653 383 0 0 1152 848 IBEditorPositions 124 @@ -15,17 +15,17 @@ 297 107 466 213 294 0 0 1600 1002 314 - 73 542 213 132 0 0 1600 1002 + 72 544 213 150 0 0 1600 1002 336 486 756 213 180 0 0 1600 1002 365 31 719 93 162 0 0 1600 1002 463 - 97 693 213 246 0 0 1600 1002 + 349 487 213 246 0 0 1600 1002 56 450 634 343 68 0 0 1280 1002 654 - 206 785 198 144 0 0 1600 1002 + 140 644 198 144 0 0 1152 848 IBFramework Version 286.0 @@ -42,6 +42,6 @@ IBLockedObjects IBSystem Version - 6F21 + 6G30 diff --git a/chimera/resources/localized/English.lproj/BrowserWindow.nib/objects.nib b/chimera/resources/localized/English.lproj/BrowserWindow.nib/objects.nib index 6ea50d4bb91c16ff7f6c317617a9ec2de61c1312..3a5bafda9055e11d58cd6d1028a66304b2c83f0e 100644 GIT binary patch literal 19032 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 IBDocumentLocation - 237 33 482 372 0 0 1600 1002 + 105 33 482 372 0 0 1600 1002 IBEditorPositions 266 - 437 533 277 90 0 0 1152 848 + 644 623 277 90 0 0 1600 1002 29 11 957 446 44 0 0 1600 1002 494 @@ -31,7 +31,11 @@ IBLastGroupID 2 + IBOpenObjects + + 29 + IBSystem Version - 6F21 + 6G30 diff --git a/chimera/resources/localized/English.lproj/MainMenu.nib/objects.nib b/chimera/resources/localized/English.lproj/MainMenu.nib/objects.nib index 639e9548c05f38c2cf97a01023d85045e6f7e550..9f05349791e4b9575af6908df77db58ebcbd89de 100644 GIT binary patch literal 10767 zcmb_i4{)5tb^rD(%la=_HjWJqIVLcKK%l@B9CwT*%g9z`%Qk1?76+Kq-6!er-F=t4 zlV!yP=ZU*ZJG2wx*gK#oQ~PACX0mBJoS+#WSFWc@sstLX_Dh?U=FNIC{HStntD*KE%P+L*PuC$wrX8}5zUp=>&q>=&BT{obAv z*EaTq+Eb}`EE3MfoMa(i$cb25g0l{sc5<*QYbQwj?{=P~+JMOV+4fvjtgWrh%02pM z&8l!L$&>}7hC5w*IvpOia=BTMuRphs)@;jtciUL55u9CJ%-*&rrbX2Dgg3?d!&xU? zfIzD-VzpS-$kwxG¹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 literal 10741 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 - - - - IBDocumentLocation - 94 26 404 250 0 0 1152 746 - IBFramework Version - 248.0 - IBSystem Version - 5S60 - - diff --git a/chimera/resources/localized/English.lproj/ProgressDialog.nib/objects.nib b/chimera/resources/localized/English.lproj/ProgressDialog.nib/objects.nib index 6377ab6fd1971ee745a4b555450a7e8e034bd5d1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 2233 zcmb7G-Am+F6u(zzrmi1TrEZ~p@}W@HzBpQ17$_Ze*CM#lnz0|)g~rSs&2By<6RW=L zHnTVR1BRI}DNAUjEoEG^NG*aG1i=TX6#Bdm`_RHt%2G-n`cmz=lNpmLUF;Q;o0F5@ zJ?D4M{oRRm7^{mUS1@!UC}!&uiZhhbB*%}BOwQdVqH$d?1QR``w2k8f3$jXq%ji{D>#4P8>_ahc-Ru1@LNyiN**>+<}lrW(2?%S5*=n_{WU0rw7$&yp2m zOd@jbB}%Vwe8cS;r3sFIPa?}O1FvaPSk%-U(NVcXACxQ?(asEvd}9P5-CQz+IhhRW zy0D5UeU9UUY1!>4(a%brTZ|!uJPSt8T|S8rpDcMLi~Z4Bu-*H8`FmIZ62fqtvBMq9;9 zhJ^|#j%u<7wA2!`HCQ{ruNDlV*bqji7_eUVvFUoPmA2&b_uuZXtz(-#CpI2}TX(~a z)gpA=MBrlsH8^eA4gOl1{N?YOcorCB*CvNwF#5jysu)Y13>Oj5@iky0`y0zzuZO+$ z5Y;vT@Y^%EupA~T|GOY(U`=irSUWF#0?pNz)zTsC_A_7?E&&Qb^wf$s3WR_nraTe+kg!4Ov($kX#=FkEXu=-@y5P z6FIEraJ^7-R;Fgn;{yZffq{_DgD57YFK~QQ7{=9{BnpP6o9NL4wn0bg4F;Xv4o>_{ z0mNjbrwqF$HJHDJ5p);~jB&Utq#Gul>1CZb)7y-S#zirg6A}LV1YK<1h5uK-qe%2F zY(ooU6aQqQ@7bE{9wg9M&nwwlQWCCids&LG*{{OLl@WPuj zTTgkT!g5b6*Bbz|nEtYH%z|vo5t+XqN3AffI+f7-J(f;u(cfWW&i!p{L|hxhkC^pE4d zd)q(y*#A}V|5)&!ioTcd*QWfv5B#ln{exM*g8kjBzdh~$dB;Ee$bT~F|2F6Up7Vd^ aT-ik>SfYD;WK - - - - IBDocumentLocation - 410 67 356 301 0 0 1152 848 - IBFramework Version - 286.0 - IBOpenObjects - - 251 - - IBSystem Version - 6F21 - - diff --git a/chimera/resources/localized/English.lproj/alert.nib/objects.nib b/chimera/resources/localized/English.lproj/alert.nib/objects.nib index 6a8f50daa6c40b62549d50aec75cf7a65de2a725..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 14759 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 diff --git a/chimera/src/application/AppComponents.mm b/chimera/src/application/AppComponents.mm index ebe8a06c200..d8cf7b31b10 100644 --- a/chimera/src/application/AppComponents.mm +++ b/chimera/src/application/AppComponents.mm @@ -37,10 +37,14 @@ * ***** END LICENSE BLOCK ***** */ #import + #import "SecurityDialogs.h" #import "CocoaPromptService.h" -#include "nsIGenericFactory.h" #import "KeychainService.h" +#import "nsDownloadListener.h" +#import "ProgressDlgController.h" + +#include "nsIGenericFactory.h" // {0ffd3880-7a1a-11d6-a384-975d1d5f86fc} #define NS_SECURITYDIALOGS_CID \ @@ -55,6 +59,27 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(SecurityDialogs); NS_GENERIC_FACTORY_CONSTRUCTOR(CocoaPromptService); NS_GENERIC_FACTORY_CONSTRUCTOR(KeychainPrompt); +//NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadListener); + +static NS_IMETHODIMP +nsDownloadListenerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) +{ + *aResult = NULL; + if (aOuter) + return NS_ERROR_NO_AGGREGATION; + + nsDownloadListener* inst; + NS_NEWXPCOM(inst, nsDownloadListener); + if (!inst) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(inst); + inst->SetDisplayFactory([ProgressDlgController sharedDownloadController]); + nsresult rv = inst->QueryInterface(aIID, aResult); + NS_RELEASE(inst); + return rv; +} + // used by MainController to register the components in which we want to override // with the Gecko embed layer. @@ -83,6 +108,12 @@ static const nsModuleComponentInfo gAppComponents[] = { NS_KEYCHAINPROMPT_CID, "@mozilla.org/wallet/single-sign-on-prompt;1", KeychainPromptConstructor + }, + { + "Download", + NS_DOWNLOAD_CID, + NS_DOWNLOAD_CONTRACTID, + nsDownloadListenerConstructor } }; diff --git a/chimera/src/application/MainController.h b/chimera/src/application/MainController.h index 2bf9fb1ce2b..33edbca4a3d 100644 --- a/chimera/src/application/MainController.h +++ b/chimera/src/application/MainController.h @@ -52,9 +52,8 @@ { IBOutlet NSApplication* mApplication; - // The following two items are used by the filter list when saving files. + // The following item is added to NSSavePanels as an accessory view IBOutlet NSView* mFilterView; - IBOutlet NSPopUpButton* mFilterList; // IBOutlet NSMenuItem* mOfflineMenuItem; IBOutlet NSMenuItem* mCloseWindowMenuItem; @@ -137,11 +136,12 @@ -(IBAction) addFolder:(id)aSender; -(IBAction) addSeparator:(id)aSender; -//Window menu actions +// Window menu actions -(IBAction) newTab:(id)aSender; -(IBAction) closeTab:(id)aSender; +-(IBAction) downloadsWindow:(id)aSender; -//Help menu actions +// Help menu actions -(IBAction) infoLink:(id)aSender; -(IBAction) feedbackLink:(id)aSender; @@ -154,7 +154,8 @@ - (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost; --(NSWindow*)getFrontmostBrowserWindow; +- (NSView*)getSavePanelView; +- (NSWindow*)getFrontmostBrowserWindow; - (MVPreferencesController *)preferencesController; - (void)displayPreferencesWindow:sender; diff --git a/chimera/src/application/MainController.mm b/chimera/src/application/MainController.mm index 9ef0177d9bf..e200d2f2e43 100644 --- a/chimera/src/application/MainController.mm +++ b/chimera/src/application/MainController.mm @@ -260,19 +260,7 @@ const int kReuseWindowOnAE = 2; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - if ([ProgressDlgController numDownloadInProgress] > 0) - { - NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?"); - NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @""); - NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel"); - NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit"); - // while the panel is up, download dialogs won't update (no timers firing) but - // downloads continue (PLEvents being processed) - if (NSRunAlertPanel(alert, message, okButton, altButton, nil) == NSAlertDefaultReturn) - return NSTerminateCancel; - } - - return NSTerminateNow; + return [[ProgressDlgController sharedDownloadController] allowTerminate]; } -(void)applicationWillTerminate: (NSNotification*)aNotification @@ -439,7 +427,7 @@ const int kReuseWindowOnAE = 2; { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) - [browserController saveDocument:NO filterView:mFilterView filterList: mFilterList]; + [browserController saveDocument:NO filterView:mFilterView]; } -(IBAction) pageSetup:(id)aSender @@ -584,6 +572,11 @@ const int kReuseWindowOnAE = 2; } } +-(IBAction) downloadsWindow:(id)aSender +{ + [[ProgressDlgController sharedDownloadController] showWindow:aSender]; +} + - (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost; { [mAddBookmarkMenuItem setEnabled:inBrowserWindowFrontmost]; @@ -591,6 +584,11 @@ const int kReuseWindowOnAE = 2; [mCreateBookmarksSeparatorMenuItem setEnabled:NO]; // separators are not implemented yet } +- (NSView*)getSavePanelView +{ + return mFilterView; +} + -(NSWindow*)getFrontmostBrowserWindow { // for some reason, [NSApp mainWindow] doesn't always work, so we have to diff --git a/chimera/src/application/nsStaticComponents.cpp b/chimera/src/application/nsStaticComponents.cpp index 1065d7b5ed2..849cbfddf5d 100644 --- a/chimera/src/application/nsStaticComponents.cpp +++ b/chimera/src/application/nsStaticComponents.cpp @@ -47,7 +47,58 @@ NSGETMODULE(_name) (nsIComponentManager* aCompMgr, \ } // NSGetModule entry points -DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsUCvJAModule) DECL_NSGETMODULE(nsUCvCnModule) DECL_NSGETMODULE(nsUCvLatinModule) DECL_NSGETMODULE(nsUCvTWModule) DECL_NSGETMODULE(nsUCvTW2Module) DECL_NSGETMODULE(nsUCvKoModule) DECL_NSGETMODULE(nsLocaleModule) DECL_NSGETMODULE(nsStringBundleModule) DECL_NSGETMODULE(nsLWBrkModule) DECL_NSGETMODULE(nsCharDetModule) DECL_NSGETMODULE(xpconnect) DECL_NSGETMODULE(cacheservice) DECL_NSGETMODULE(necko_core_and_primary_protocols) DECL_NSGETMODULE(necko_secondary_protocols) DECL_NSGETMODULE(nsURILoaderModule) DECL_NSGETMODULE(nsPrefModule) DECL_NSGETMODULE(nsCJVMManagerModule) DECL_NSGETMODULE(nsSecurityManagerModule) DECL_NSGETMODULE(nsChromeModule) DECL_NSGETMODULE(nsRDFModule) DECL_NSGETMODULE(nsParserModule) DECL_NSGETMODULE(nsGfxMacModule) DECL_NSGETMODULE(nsGfx2Module) DECL_NSGETMODULE(nsImageLib2Module) DECL_NSGETMODULE(nsPNGDecoderModule) DECL_NSGETMODULE(nsGIFModule2) DECL_NSGETMODULE(nsJPEGDecoderModule) DECL_NSGETMODULE(nsPluginModule) DECL_NSGETMODULE(javascript__protocol) DECL_NSGETMODULE(DOM_components) DECL_NSGETMODULE(nsViewModule) DECL_NSGETMODULE(nsWidgetMacModule) DECL_NSGETMODULE(nsContentModule) DECL_NSGETMODULE(nsLayoutModule) DECL_NSGETMODULE(nsMorkModule) DECL_NSGETMODULE(docshell_provider) DECL_NSGETMODULE(embedcomponents) DECL_NSGETMODULE(Browser_Embedding_Module) DECL_NSGETMODULE(nsEditorModule) DECL_NSGETMODULE(nsTransactionManagerModule) DECL_NSGETMODULE(nsTextServicesModule) DECL_NSGETMODULE(nsProfileModule) DECL_NSGETMODULE(Session_History_Module) DECL_NSGETMODULE(application) DECL_NSGETMODULE(nsCookieModule) DECL_NSGETMODULE(nsXMLExtrasModule) DECL_NSGETMODULE(nsUniversalCharDetModule) DECL_NSGETMODULE(BOOT) DECL_NSGETMODULE(NSS) +DECL_NSGETMODULE(UcharUtil) +DECL_NSGETMODULE(nsUConvModule) +DECL_NSGETMODULE(nsUCvJAModule) +DECL_NSGETMODULE(nsUCvCnModule) +DECL_NSGETMODULE(nsUCvLatinModule) +DECL_NSGETMODULE(nsUCvTWModule) +DECL_NSGETMODULE(nsUCvTW2Module) +DECL_NSGETMODULE(nsUCvKoModule) +DECL_NSGETMODULE(nsLocaleModule) +DECL_NSGETMODULE(nsStringBundleModule) +DECL_NSGETMODULE(nsLWBrkModule) +DECL_NSGETMODULE(nsCharDetModule) +DECL_NSGETMODULE(xpconnect) +DECL_NSGETMODULE(cacheservice) +DECL_NSGETMODULE(necko_core_and_primary_protocols) +DECL_NSGETMODULE(necko_secondary_protocols) +DECL_NSGETMODULE(nsURILoaderModule) +DECL_NSGETMODULE(nsPrefModule) +DECL_NSGETMODULE(nsCJVMManagerModule) +DECL_NSGETMODULE(nsSecurityManagerModule) +DECL_NSGETMODULE(nsChromeModule) +DECL_NSGETMODULE(nsRDFModule) +DECL_NSGETMODULE(nsParserModule) +DECL_NSGETMODULE(nsGfxMacModule) +DECL_NSGETMODULE(nsGfx2Module) +DECL_NSGETMODULE(nsImageLib2Module) +DECL_NSGETMODULE(nsPNGDecoderModule) +DECL_NSGETMODULE(nsGIFModule2) +DECL_NSGETMODULE(nsJPEGDecoderModule) +DECL_NSGETMODULE(nsPluginModule) +DECL_NSGETMODULE(javascript__protocol) +DECL_NSGETMODULE(JS_component_loader) +DECL_NSGETMODULE(DOM_components) +DECL_NSGETMODULE(nsViewModule) +DECL_NSGETMODULE(nsWidgetMacModule) +DECL_NSGETMODULE(nsContentModule) +DECL_NSGETMODULE(nsLayoutModule) +DECL_NSGETMODULE(nsMorkModule) +DECL_NSGETMODULE(docshell_provider) +DECL_NSGETMODULE(embedcomponents) +DECL_NSGETMODULE(Browser_Embedding_Module) +DECL_NSGETMODULE(nsEditorModule) +DECL_NSGETMODULE(nsTransactionManagerModule) +DECL_NSGETMODULE(nsTextServicesModule) +DECL_NSGETMODULE(nsProfileModule) +DECL_NSGETMODULE(Session_History_Module) +DECL_NSGETMODULE(application) +DECL_NSGETMODULE(nsCookieModule) +DECL_NSGETMODULE(nsXMLExtrasModule) +DECL_NSGETMODULE(nsUniversalCharDetModule) +DECL_NSGETMODULE(BOOT) +DECL_NSGETMODULE(NSS) #line 52 "nsStaticComponents.cpp.in" /** @@ -55,7 +106,58 @@ DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsU */ static nsStaticModuleInfo gStaticModuleInfo[] = { #define MODULE(_name) { (#_name), NSGETMODULE(_name) } - MODULE(UcharUtil), MODULE(nsUConvModule), MODULE(nsUCvJAModule), MODULE(nsUCvCnModule), MODULE(nsUCvLatinModule), MODULE(nsUCvTWModule), MODULE(nsUCvTW2Module), MODULE(nsUCvKoModule), MODULE(nsLocaleModule), MODULE(nsStringBundleModule), MODULE(nsLWBrkModule), MODULE(nsCharDetModule), MODULE(xpconnect), MODULE(cacheservice), MODULE(necko_core_and_primary_protocols), MODULE(necko_secondary_protocols), MODULE(nsURILoaderModule), MODULE(nsPrefModule), MODULE(nsCJVMManagerModule), MODULE(nsSecurityManagerModule), MODULE(nsChromeModule), MODULE(nsRDFModule), MODULE(nsParserModule), MODULE(nsGfxMacModule), MODULE(nsGfx2Module), MODULE(nsImageLib2Module), MODULE(nsPNGDecoderModule), MODULE(nsGIFModule2), MODULE(nsJPEGDecoderModule), MODULE(nsPluginModule), MODULE(javascript__protocol), MODULE(DOM_components), MODULE(nsViewModule), MODULE(nsWidgetMacModule), MODULE(nsContentModule), MODULE(nsLayoutModule), MODULE(nsMorkModule), MODULE(docshell_provider), MODULE(embedcomponents), MODULE(Browser_Embedding_Module), MODULE(nsEditorModule), MODULE(nsTransactionManagerModule), MODULE(nsTextServicesModule), MODULE(nsProfileModule), MODULE(Session_History_Module), MODULE(application), MODULE(nsCookieModule), MODULE(nsXMLExtrasModule), MODULE(nsUniversalCharDetModule), MODULE(BOOT), MODULE(NSS), +MODULE(UcharUtil), +MODULE(nsUConvModule), +MODULE(nsUCvJAModule), +MODULE(nsUCvCnModule), +MODULE(nsUCvLatinModule), +MODULE(nsUCvTWModule), +MODULE(nsUCvTW2Module), +MODULE(nsUCvKoModule), +MODULE(nsLocaleModule), +MODULE(nsStringBundleModule), +MODULE(nsLWBrkModule), +MODULE(nsCharDetModule), +MODULE(xpconnect), +MODULE(cacheservice), +MODULE(necko_core_and_primary_protocols), +MODULE(necko_secondary_protocols), +MODULE(nsURILoaderModule), +MODULE(nsPrefModule), +MODULE(nsCJVMManagerModule), +MODULE(nsSecurityManagerModule), +MODULE(nsChromeModule), +MODULE(nsRDFModule), +MODULE(nsParserModule), +MODULE(nsGfxMacModule), +MODULE(nsGfx2Module), +MODULE(nsImageLib2Module), +MODULE(nsPNGDecoderModule), +MODULE(nsGIFModule2), +MODULE(nsJPEGDecoderModule), +MODULE(nsPluginModule), +MODULE(javascript__protocol), +MODULE(JS_component_loader), +MODULE(DOM_components), +MODULE(nsViewModule), +MODULE(nsWidgetMacModule), +MODULE(nsContentModule), +MODULE(nsLayoutModule), +MODULE(nsMorkModule), +MODULE(docshell_provider), +MODULE(embedcomponents), +MODULE(Browser_Embedding_Module), +MODULE(nsEditorModule), +MODULE(nsTransactionManagerModule), +MODULE(nsTextServicesModule), +MODULE(nsProfileModule), +MODULE(Session_History_Module), +MODULE(application), +MODULE(nsCookieModule), +MODULE(nsXMLExtrasModule), +MODULE(nsUniversalCharDetModule), +MODULE(BOOT), +MODULE(NSS), #line 60 "nsStaticComponents.cpp.in" }; diff --git a/chimera/src/bookmarks/BookmarksDataSource.mm b/chimera/src/bookmarks/BookmarksDataSource.mm index de6cf71b6ac..e69de29bb2d 100644 --- a/chimera/src/bookmarks/BookmarksDataSource.mm +++ b/chimera/src/bookmarks/BookmarksDataSource.mm @@ -1,883 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import "NSString+Utils.h" - -#import "BookmarksDataSource.h" -#import "BookmarkInfoController.h" -#import "SiteIconProvider.h" - -#include "nsCOMPtr.h" -#include "nsIContent.h" -#include "nsIDocument.h" -#include "nsIDocumentObserver.h" -#include "nsIDOMDocument.h" -#include "nsIDOMElement.h" -#include "nsINamespaceManager.h" - -#include "nsVoidArray.h" - -#import "BookmarksService.h" - -@interface BookmarksDataSource(Private) - -- (void)restoreFolderExpandedStates; -- (void)refreshChildrenOfItem:(nsIContent*)item; - -@end - -const int kBookmarksRootItemTag = -2; - -@implementation BookmarksDataSource - --(id) init -{ - if ( (self = [super init]) ) - { - mCachedHref = nil; - } - return self; -} - -- (void)dealloc -{ -// NSLog(@"BookmarksDataSource dealloc"); - [super dealloc]; -} - --(void) awakeFromNib -{ - // make sure these are disabled at the start since the outliner - // starts off with no selection. - [mEditBookmarkButton setEnabled:NO]; - [mDeleteBookmarkButton setEnabled:NO]; -} - --(void) windowClosing -{ - BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManagerDontAlloc]; - [bmManager removeBookmarksClient:self]; -} - --(void) ensureBookmarks -{ - if (mRegisteredClient) - return; - - BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager]; - [bmManager addBookmarksClient:self]; - mRegisteredClient = YES; - - [mOutlineView setTarget: self]; - [mOutlineView setDoubleAction: @selector(openBookmark:)]; - [mOutlineView setDeleteAction: @selector(deleteBookmarks:)]; - [mOutlineView reloadData]; - [self restoreFolderExpandedStates]; -} - --(IBAction)addBookmark:(id)aSender -{ - [self addBookmark: aSender useSelection: YES isFolder: NO URL:nil title:nil]; -} - --(IBAction)addFolder:(id)aSender -{ - [self addBookmark: aSender useSelection: YES isFolder: YES URL:nil title:nil]; -} - --(void)addBookmark:(id)aSender useSelection:(BOOL)aUseSel isFolder:(BOOL)aIsFolder URL:(NSString*)aURL title:(NSString*)aTitle -{ - // We use the selected item to determine the parent only if aUseSel is YES. - BookmarkItem* item = nil; - if (aUseSel && ([mOutlineView numberOfSelectedRows] == 1)) - { - // There is only one selected row. If it is a folder, use it as our parent. - // Otherwise, use our parent, - int index = [mOutlineView selectedRow]; - item = [mOutlineView itemAtRow: index]; - if (![mOutlineView isExpandable: item]) { - // We can't be used as the parent. Try our parent. - nsIContent* content = [item contentNode]; - if (!content) - return; - - nsCOMPtr parentContent; - content->GetParent(*getter_AddRefs(parentContent)); - nsCOMPtr root; - BookmarksService::GetRootContent(getter_AddRefs(root)); - - // The root has no item, so we don't need to do a lookup unless we - // aren't the root. - if (parentContent != root) { - PRUint32 contentID; - parentContent->GetContentID(&contentID); - item = BookmarksService::GetWrapperFor(contentID); - } - } - } - - [self addBookmark:aSender withParent:item isFolder:aIsFolder URL:aURL title:aTitle]; -} - --(void)addBookmark:(id)aSender withParent:(BookmarkItem*)bmItem isFolder:(BOOL)aIsFolder URL:(NSString*)aURL title:(NSString*)aTitle -{ - NSString* titleString = aTitle; - NSString* urlString = aURL; - - if (!aIsFolder) - { - // If no URL and title were specified, get them from the current page. - if (!aURL || !aTitle) - [[mBrowserWindowController getBrowserWrapper] getTitle:&titleString andHref:&urlString]; - - mCachedHref = [NSString stringWithString:urlString]; - [mCachedHref retain]; - - } else { // Folder - mCachedHref = nil; - titleString = NSLocalizedString(@"NewBookmarkFolder", @""); - } - - NSTextField* textField = [mBrowserWindowController getAddBookmarkTitle]; - NSString* bookmarkTitle = titleString; - NSString* cleanedTitle = [bookmarkTitle stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "]; - - [textField setStringValue: cleanedTitle]; - - [mBrowserWindowController cacheBookmarkDS: self]; - - // Show/hide the bookmark all tabs checkbox as appropriate. - NSTabView* tabView = [mBrowserWindowController getTabBrowser]; - id checkbox = [mBrowserWindowController getAddBookmarkCheckbox]; - BOOL hasSuperview = [checkbox superview] != nil; - if (aIsFolder && hasSuperview) { - // Just don't show it at all. - [checkbox removeFromSuperview]; - [checkbox retain]; - } - else if (!aIsFolder && !hasSuperview) { - // Put it back in. - [[[mBrowserWindowController getAddBookmarkSheetWindow] contentView] addSubview: checkbox]; - [checkbox autorelease]; - } - - // Enable the bookmark all tabs checkbox if appropriate. - if (!aIsFolder) - [[mBrowserWindowController getAddBookmarkCheckbox] setEnabled: ([tabView numberOfTabViewItems] > 1)]; - - // Build up the folder list. - NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder]; - [popup removeAllItems]; - [popup addItemWithTitle: NSLocalizedString(@"BookmarksRootName", @"")]; - [[popup lastItem] setTag:kBookmarksRootItemTag]; - - BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager]; - [bmManager buildFlatFolderList:[popup menu] fromRoot:NULL]; - - int itemIndex = [popup indexOfItemWithTag:[bmItem intContentID]]; - if (itemIndex != -1) - [popup selectItemAtIndex:itemIndex]; - - [popup synchronizeTitleAndSelectedItem]; - - [NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow] - modalForWindow: [mBrowserWindowController window] - modalDelegate: nil //self - didEndSelector: nil //@selector(sheetDidEnd:) - contextInfo: nil]; -} - --(void)endAddBookmark: (int)aCode -{ - if (aCode == 0) - return; - - BOOL isGroup = NO; - id checkbox = [mBrowserWindowController getAddBookmarkCheckbox]; - if (([checkbox superview] != nil) && [checkbox isEnabled] && ([checkbox state] == NSOnState)) - { - [mCachedHref release]; - mCachedHref = nil; - isGroup = YES; - } - - BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager]; - NSString* titleString = [[mBrowserWindowController getAddBookmarkTitle] stringValue]; - - // Figure out the parent element. - nsCOMPtr parentContent; - - NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder]; - NSMenuItem* selectedItem = [popup selectedItem]; - int tag = [selectedItem tag]; - if (tag != kBookmarksRootItemTag) - { - BookmarkItem* item = BookmarksService::GetWrapperFor(tag); - // Get the content node. - parentContent = [item contentNode]; - } - - if (isGroup) - { - id tabBrowser = [mBrowserWindowController getTabBrowser]; - int count = [tabBrowser numberOfTabViewItems]; - - NSMutableArray* itemsArray = [[NSMutableArray alloc] initWithCapacity:count]; - - for (int i = 0; i < count; i++) - { - BrowserWrapper* browserWrapper = (BrowserWrapper*)[[tabBrowser tabViewItemAtIndex: i] view]; - - NSString* titleString = nil; - NSString* hrefString = nil; - [browserWrapper getTitle:&titleString andHref:&hrefString]; - - NSDictionary* itemDict = [NSDictionary dictionaryWithObjectsAndKeys: - titleString, @"title", - hrefString, @"href", - nil]; - [itemsArray addObject:itemDict]; - } - - [bmManager addNewBookmarkGroup:titleString items:itemsArray withParent:parentContent]; - } - else - { - if (mCachedHref) - { - [bmManager addNewBookmark:mCachedHref title:titleString withParent:parentContent]; - [mCachedHref release]; - mCachedHref = nil; - } - else - [bmManager addNewBookmarkFolder:titleString withParent:parentContent]; - } -} - --(IBAction)deleteBookmarks: (id)aSender -{ - int index = [mOutlineView selectedRow]; - if (index == -1) - return; - - // first, see how many items are selected - BOOL haveBookmarks = NO; - - NSEnumerator* testSelRows = [mOutlineView selectedRowEnumerator]; - for (NSNumber* currIndex = [testSelRows nextObject]; - currIndex != nil; - currIndex = [testSelRows nextObject]) - { - index = [currIndex intValue]; - BookmarkItem* item = [mOutlineView itemAtRow: index]; - if ([mOutlineView isExpandable: item]) { - // dumb check to see if we're deleting an empty folder. Should really - // recurse down - if ([self outlineView:mOutlineView numberOfChildrenOfItem: item] > 0) - haveBookmarks = YES; - } else - haveBookmarks = YES; - } - - // ideally, we should count the number of doomed bookmarks and tell the user - if (haveBookmarks) { - NSString *alert = NSLocalizedString(@"DeteleBookmarksAlert",@""); - NSString *message = NSLocalizedString(@"DeteleBookmarksMsg",@""); - NSString *okButton = NSLocalizedString(@"DeteleBookmarksOKButton",@""); - NSString *cancelButton = NSLocalizedString(@"DeteleBookmarksCancelButton",@""); - if (NSRunAlertPanel(alert, message, okButton, cancelButton, nil) != NSAlertDefaultReturn) - return; - } - - // The alert panel was the key window. As soon as we dismissed it, Cocoa will - // pick a new one for us. Ideally, it'll be the window we were using when - // we clicked the delete button. However, if by chance the BookmarkInfoController - // is visible, it will become the key window since it's a panel. If we then delete - // the bookmark and try to close the window before we've setup a new bookmark, - // we'll trigger the windowDidResignKey message, which will try to update the bookmark - // we just deleted, and things will crash. So, we'll trigger windowDidResignKey now - // and avoid the unpleasentness of a crash log. - - if (![[mBrowserWindowController window] isKeyWindow]) - [[mBrowserWindowController window] makeKeyWindow]; - - // we'll run into problems if a parent item and one if its children are both selected. - // A cheap way of having to avoid scanning the list to remove children is to have the - // outliner collapse all items that are being deleted. This will cull the selection - // for us and eliminate any children that happened to be selected. - NSEnumerator* selRows = [mOutlineView selectedRowEnumerator]; - for (NSNumber* currIndex = [selRows nextObject]; - currIndex != nil; - currIndex = [selRows nextObject]) { - index = [currIndex intValue]; - BookmarkItem* item = [mOutlineView itemAtRow: index]; - [mOutlineView collapseItem: item]; - } - - // create array of items we need to delete. Deleting items out of of the - // selection array is problematic for some reason. - NSMutableArray* itemsToDelete = [[[NSMutableArray alloc] init] autorelease]; - selRows = [mOutlineView selectedRowEnumerator]; - for (NSNumber* currIndex = [selRows nextObject]; - currIndex != nil; - currIndex = [selRows nextObject]) { - index = [currIndex intValue]; - BookmarkItem* item = [mOutlineView itemAtRow: index]; - [itemsToDelete addObject: item]; - } - - // delete all bookmarks that are in our array - int count = [itemsToDelete count]; - for (int i = 0; i < count; i++) { - BookmarkItem* item = [itemsToDelete objectAtIndex: i]; - [self deleteBookmark: item]; - } - - // restore selection to location near last item deleted or last item - int total = [mOutlineView numberOfRows]; - if (index >= total) - index = total - 1; - [mOutlineView selectRow: index byExtendingSelection: NO]; - // lame, but makes sure we catch all delete events in Info Panel - [[NSNotificationCenter defaultCenter] postNotificationName:@"NSOutlineViewSelectionDidChangeNotification" object:mOutlineView]; -} - --(void)deleteBookmark:(id)aItem -{ - [aItem remove]; -} - --(IBAction)openBookmark: (id)aSender -{ - int index = [mOutlineView selectedRow]; - if (index == -1) - return; - - id item = [mOutlineView itemAtRow: index]; - if (!item) - return; - - if ([item isGroup]) - { - NSArray* groupURLs = [[BookmarksManager sharedBookmarksManager] getBookmarkGroupURIs:item]; - [mBrowserWindowController openTabGroup:groupURLs replaceExistingTabs:YES]; - } - else if ([mOutlineView isExpandable: item]) - { - if ([mOutlineView isItemExpanded: item]) - [mOutlineView collapseItem: item]; - else - [mOutlineView expandItem: item]; - } - else - { - // if the command key is down, follow the command-click pref - if (([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) && - [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.opentabfor.middleclick" withSuccess:NULL]) - { - BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL]; - [mBrowserWindowController openNewTabWithURL:[item url] referrer:nil loadInBackground: loadInBackground]; - } - else - [[mBrowserWindowController getBrowserWrapper] loadURI:[item url] referrer:nil flags:NSLoadFlagsNone activate:YES]; - } -} - --(IBAction)openBookmarkInNewTab:(id)aSender -{ - int index = [mOutlineView selectedRow]; - if (index == -1) - return; - - if ([mOutlineView numberOfSelectedRows] == 1) - { - BookmarkItem* item = [mOutlineView itemAtRow: index]; - BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL]; - [mBrowserWindowController openNewTabWithURL:[item url] referrer:nil loadInBackground: loadInBackground]; - } -} - --(IBAction)openBookmarkInNewWindow:(id)aSender -{ - int index = [mOutlineView selectedRow]; - if (index == -1) - return; - if ([mOutlineView numberOfSelectedRows] == 1) - { - BookmarkItem* item = [mOutlineView itemAtRow: index]; - - BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL]; - - if ([item isGroup]) - [mBrowserWindowController openNewWindowWithGroup:[item contentNode] loadInBackground:loadInBackground]; - else - [mBrowserWindowController openNewWindowWithURL:[item url] referrer: nil loadInBackground: loadInBackground]; - } -} - --(IBAction)showBookmarkInfo:(id)aSender -{ - BookmarkInfoController *bic = [BookmarkInfoController sharedBookmarkInfoController]; - - int index = [mOutlineView selectedRow]; - BookmarkItem* item = [mOutlineView itemAtRow: index]; - [bic setBookmark:item]; - - [bic showWindow:bic]; -} - -- (void)restoreFolderExpandedStates -{ - int curRow = 0; - - while (curRow < [mOutlineView numberOfRows]) - { - id item = [mOutlineView itemAtRow:curRow]; - - if (item) - { - nsCOMPtr content; - content = [item contentNode]; - - PRBool isOpen = content && content->HasAttr(kNameSpaceID_None, BookmarksService::gOpenAtom); - if (isOpen) - [mOutlineView expandItem: item]; - else - [mOutlineView collapseItem: item]; - } - - curRow ++; - } -} - -- (void)refreshChildrenOfItem:(nsIContent*)item -{ - BookmarkItem* bmItem = nil; - - nsCOMPtr parent; - if (item) - item->GetParent(*getter_AddRefs(parent)); - if (parent) // we're not the root - bmItem = [[BookmarksManager sharedBookmarksManager] getWrapperForContent:item]; - - [self reloadDataForItem:bmItem reloadChildren:YES]; -} - -#pragma mark - - -// BookmarksClient protocol - -- (void)bookmarkAdded:(nsIContent*)bookmark inContainer:(nsIContent*)container isChangedRoot:(BOOL)isRoot -{ - [self refreshChildrenOfItem:container]; -} - -- (void)bookmarkRemoved:(nsIContent*)bookmark inContainer:(nsIContent*)container isChangedRoot:(BOOL)isRoot -{ - [self refreshChildrenOfItem:container]; -} - -- (void)bookmarkChanged:(nsIContent*)bookmark -{ - BookmarkItem* item = [[BookmarksManager sharedBookmarksManager] getWrapperForContent:bookmark]; - [self reloadDataForItem:item reloadChildren:NO]; -} - -- (void)specialFolder:(EBookmarksFolderType)folderType changedTo:(nsIContent*)newFolderContent -{ - // change the icons - - -} - -#pragma mark - - -// -// outlineView:shouldEditTableColumn:item: (delegate method) -// -// Called by the outliner to determine whether or not we should allow the -// user to edit this item. We're leaving it off for now, becaue there are -// some usability issues with inline editing (no undo, Escape doesn't work). -- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item -{ - return NO; //([[tableColumn identifier] isEqualToString:@"name"]); -} - -- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item -{ - if (!mRegisteredClient) return nil; - - nsCOMPtr content; - if (!item) - BookmarksService::GetRootContent(getter_AddRefs(content)); - else - content = [item contentNode]; - - nsCOMPtr child; - content->ChildAt(index, *getter_AddRefs(child)); - if ( child ) - return BookmarksService::GetWrapperFor(child); - - return nil; -} - -- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item -{ - if (!mRegisteredClient) return NO; - - if (!item) - return YES; // The root node is always open. - - return [item isFolder]; -} - -- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item -{ - if (!mRegisteredClient) return 0; - - nsCOMPtr content; - if (!item) - BookmarksService::GetRootContent(getter_AddRefs(content)); - else - content = [item contentNode]; - - PRInt32 childCount; - content->ChildCount(childCount); - - return childCount; -} - -- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item -{ - if (!mRegisteredClient) return nil; - - NSString *columnName = [tableColumn identifier]; - NSMutableAttributedString *cellValue = nil; - - if ([columnName isEqualToString: @"name"]) - { - NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - - nsIContent* content = [item contentNode]; - nsAutoString nameAttr; - content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr); - - //Set cell's textual contents - //[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString: nameAttr]]; - cellValue = [[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]]; - - //Create an attributed string to hold the empty attachment, then release the components. - NSMutableAttributedString* attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; - [textAttachment release]; - [fileWrapper release]; - - //Get the cell of the text attachment. - NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell]; - - nsCOMPtr elt(do_QueryInterface(content)); - NSImage* bookmarkImage = BookmarksService::CreateIconForBookmark(elt); - [attachmentAttrStringCell setImage:bookmarkImage]; - - //Insert the image - [cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString]; - - //Tweak the baseline to vertically center the text. - [cellValue addAttribute:NSBaselineOffsetAttributeName - value:[NSNumber numberWithFloat:-3.0] - range:NSMakeRange(0, 1)]; - } - return cellValue; -} - -- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item -{ - // object is really an NSString, even though objectValueForTableColumn returns NSAttributedStrings. - NSString *columnName = [tableColumn identifier]; - if ( [columnName isEqualTo:@"name"] ) - { - const unichar kAttachmentCharacter = NSAttachmentCharacter; - - NSMutableString* mutableString = [NSMutableString stringWithString:object]; - [mutableString replaceOccurrencesOfString:[NSString stringWithCharacters:&kAttachmentCharacter length:1] withString:@"" options:0 range:NSMakeRange(0, [mutableString length])]; - - nsAutoString nameAttr; - [mutableString assignTo_nsAString:nameAttr]; - - // stash it into the DOM - BookmarkItem* bmItem = (BookmarkItem*)item; - nsIContent* content = [bmItem contentNode]; - if (content) - content->SetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr, PR_TRUE); - - [bmItem itemChanged:YES]; - } -} - -- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard -{ - if (!mRegisteredClient) return NO; - -#ifdef FILTER_DESCENDANT_ON_DRAG - NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items); -#else - NSArray *toDrag = items; -#endif - int count = [toDrag count]; - if (count > 0) { - // Create Pasteboard Data - NSMutableArray *draggedIDs = [NSMutableArray arrayWithCapacity: count]; - - for (int i = 0; i < count; i++) - [draggedIDs addObject: [[toDrag objectAtIndex: i] contentID]]; - - if (count == 1) { - // if we have just one item, we add some more flavours - [pboard declareTypes: [NSArray arrayWithObjects: - @"MozBookmarkType", NSURLPboardType, NSStringPboardType, nil] owner: self]; - [pboard setPropertyList: draggedIDs forType: @"MozBookmarkType"]; - - NSString* itemURL = [[toDrag objectAtIndex: 0] url]; - [pboard setString:itemURL forType: NSStringPboardType]; - [[NSURL URLWithString:itemURL] writeToPasteboard: pboard]; - // maybe construct the @"MozURLType" type here also - } - else { - // multiple bookmarks. Arrays of strings or NSURLs seem to - // confuse receivers. Not sure what the correct way is. - [pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self]; - [pboard setPropertyList: draggedIDs forType: @"MozBookmarkType"]; - } - - return YES; - } - - return NO; -} - - -- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)index -{ - if (!mRegisteredClient) return NSDragOperationNone; - - NSArray* types = [[info draggingPasteboard] types]; - BOOL isCopy = ([info draggingSourceOperationMask] == NSDragOperationCopy); - - // if the index is -1, deny the drop - if (index == NSOutlineViewDropOnItemIndex) - return NSDragOperationNone; - - if ([types containsObject: @"MozBookmarkType"]) - { - NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"]; - - BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem(); - return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs, isCopy)) ? NSDragOperationGeneric : NSDragOperationNone; - } - - if ([types containsObject: @"MozURLType"]) - return NSDragOperationGeneric; - - if ([types containsObject: NSStringPboardType]) - return NSDragOperationGeneric; - - if ([types containsObject: NSURLPboardType]) - return NSDragOperationGeneric; - - return NSDragOperationNone; -} - -- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id )info item:(id)item childIndex:(int)index -{ - if (!mRegisteredClient) return NO; - - NSArray* types = [[info draggingPasteboard] types]; - BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem(); - BOOL isCopy = ([info draggingSourceOperationMask] == NSDragOperationCopy); - - BookmarkItem* beforeItem = [self outlineView:ov child:index ofItem:item]; - if ([types containsObject: @"MozBookmarkType"]) - { - NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"]; - return BookmarksService::PerformBookmarkDrop(parent, beforeItem, index, draggedItems, isCopy); - } - else if ([types containsObject: @"MozURLType"]) - { - NSDictionary* proxy = [[info draggingPasteboard] propertyListForType: @"MozURLType"]; - return BookmarksService::PerformProxyDrop(parent, beforeItem, proxy); - } - else if ([types containsObject: NSStringPboardType]) - { - NSString* draggedText = [[info draggingPasteboard] stringForType:NSStringPboardType]; - return BookmarksService::PerformURLDrop(parent, beforeItem, draggedText, draggedText); - } - else if ([types containsObject: NSURLPboardType]) - { - NSURL* urlData = [NSURL URLFromPasteboard:[info draggingPasteboard]]; - return BookmarksService::PerformURLDrop(parent, beforeItem, [urlData absoluteString], [urlData absoluteString]); - } - - return NO; -} - -- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)item -{ - if (!mRegisteredClient) return @""; - - NSString* descStr = nil; - NSString* hrefStr = nil; - nsIContent* content = [item contentNode]; - nsAutoString value; - - content->GetAttr(kNameSpaceID_None, BookmarksService::gDescriptionAtom, value); - if (value.Length()) - descStr = [NSString stringWith_nsAString:value]; - - // Only description for folders - if ([item isFolder]) - return descStr; - - // Extract the URL from the item - content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, value); - if (value.Length()) - hrefStr = [NSString stringWith_nsAString:value]; - - if (!hrefStr) - return descStr; - else if (!descStr) - return hrefStr; - - // Display both URL and description - return [NSString stringWithFormat:@"%@\n%@", hrefStr, descStr]; -} - -/* -- (NSMenu *)outlineView:(NSOutlineView *)outlineView contextMenuForItem:(id)item -{ - // TODO - return (custom?) context menu for item here. - // Note that according to HIG, there should never be disabled items in - // a context menu - instead, items that do not apply should be removed. - // We could nicely do that here. -} -*/ - -- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren -{ - if (!item) - [mOutlineView reloadData]; - else - [mOutlineView reloadItem: item reloadChildren: aReloadChildren]; -} - -- (BOOL)haveSelectedRow -{ - return ([mOutlineView selectedRow] != -1); -} - --(void)outlineViewSelectionDidChange: (NSNotification*) aNotification -{ - BookmarkInfoController *bic = [BookmarkInfoController sharedBookmarkInfoController]; - int index = [mOutlineView selectedRow]; - if (index == -1) - { - [mEditBookmarkButton setEnabled:NO]; - [mDeleteBookmarkButton setEnabled:NO]; - [bic close]; - } - else - { - BookmarkItem* item = [mOutlineView itemAtRow: index]; - - [mEditBookmarkButton setEnabled:YES]; - [mDeleteBookmarkButton setEnabled:![item isToobarRoot]]; - if ([[bic window] isVisible]) - [bic setBookmark:[mOutlineView itemAtRow:index]]; - } -} - --(BOOL)validateMenuItem:(NSMenuItem*)aMenuItem -{ - int index = [mOutlineView selectedRow]; - BOOL haveSelection = (index != -1); - BOOL isBookmark = NO; - BOOL isGroup = NO; - - BookmarkItem* item = nil; - - if (haveSelection) - { - item = [mOutlineView itemAtRow: index]; - isBookmark = ([mOutlineView isExpandable:item] == NO); - isGroup = [item isGroup]; - } - - // Bookmarks and Bookmark Groups can be opened in a new window - if (([aMenuItem action] == @selector(openBookmarkInNewWindow:))) - return (isBookmark || isGroup); - - // Only Bookmarks can be opened in new tabs - if (([aMenuItem action] == @selector(openBookmarkInNewTab:))) - return isBookmark && [mBrowserWindowController newTabsAllowed]; - - if (([aMenuItem action] == @selector(showBookmarkInfo:))) - return haveSelection; - - if (([aMenuItem action] == @selector(deleteBookmarks:))) - return haveSelection && ![item isToobarRoot]; // should deal with multiple selections - - if (([aMenuItem action] == @selector(addFolder:))) - return YES; - - return YES; -} - -- (void)outlineViewItemWillExpand:(NSNotification *)notification -{ - BookmarkItem* item = [[notification userInfo] objectForKey:[[[notification userInfo] allKeys] objectAtIndex: 0]]; - [item contentNode]->SetAttr(kNameSpaceID_None, BookmarksService::gOpenAtom, NS_LITERAL_STRING("true"), PR_FALSE); -} - -- (void)outlineViewItemWillCollapse:(NSNotification *)notification -{ - BookmarkItem* item = [[notification userInfo] objectForKey:[[[notification userInfo] allKeys] objectAtIndex: 0]]; - [item contentNode]->UnsetAttr(kNameSpaceID_None, BookmarksService::gOpenAtom, PR_FALSE); -} - -@end - diff --git a/chimera/src/browser/BrowserTabView.mm b/chimera/src/browser/BrowserTabView.mm index f215b134dbe..a40bfd8ce33 100644 --- a/chimera/src/browser/BrowserTabView.mm +++ b/chimera/src/browser/BrowserTabView.mm @@ -100,6 +100,7 @@ - (BOOL)isOpaque { + // see http://developer.apple.com/qa/qa2001/qa1117.html if ( ([self tabViewType] == NSNoTabsBezelBorder) && (NSAppKitVersionNumber < 633) ) return NO; diff --git a/chimera/src/browser/BrowserWindow.mm b/chimera/src/browser/BrowserWindow.mm index 68592f4ae3a..e69de29bb2d 100644 --- a/chimera/src/browser/BrowserWindow.mm +++ b/chimera/src/browser/BrowserWindow.mm @@ -1,94 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Chimera code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import "BrowserWindow.h" -#import "BrowserWindowController.h" -#import "AutoCompleteTextField.h" - -static const int kEscapeKeyCode = 53; - -@implementation BrowserWindow - -- (void)dealloc -{ - [super dealloc]; -} - -- (BOOL)makeFirstResponder:(NSResponder*)responder -{ - NSResponder* oldResponder = [self firstResponder]; - BOOL madeFirstResponder = [super makeFirstResponder:responder]; - if (madeFirstResponder && oldResponder != [self firstResponder]) - [(BrowserWindowController*)[self delegate] focusChangedFrom:oldResponder to:[self firstResponder]]; - return madeFirstResponder; -} - -- (void)sendEvent:(NSEvent *)theEvent -{ - // We need this hack because NSWindow::sendEvent will eat the escape key - // and won't pass it down to the key handler of responders in the window. - // We have to override sendEvent for all of our escape key needs. - if ([theEvent type] == NSKeyDown && - [theEvent keyCode] == kEscapeKeyCode && [self firstResponder] == [mAutoCompleteTextField fieldEditor]) - [mAutoCompleteTextField revertText]; - else - [super sendEvent:theEvent]; -} - -- (BOOL)suppressMakeKeyFront -{ - return mSuppressMakeKeyFront; -} - -- (void)setSuppressMakeKeyFront:(BOOL)inSuppress -{ - mSuppressMakeKeyFront = inSuppress; -} - -// accessor for the 'URL' Apple Event attribute -- (NSString*)getURL -{ - BrowserWindowController* windowController = (BrowserWindowController*)[self delegate]; - - NSString* titleString = nil; - NSString* urlString = nil; - - [[windowController getBrowserWrapper] getTitle:&titleString andHref:&urlString]; - return urlString; -} - -@end diff --git a/chimera/src/browser/BrowserWindowController.h b/chimera/src/browser/BrowserWindowController.h index eb6789343dd..063a881b02a 100644 --- a/chimera/src/browser/BrowserWindowController.h +++ b/chimera/src/browser/BrowserWindowController.h @@ -109,12 +109,12 @@ typedef enum IBOutlet NSTextField* mLocationSheetURLField; IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock IBOutlet PageProxyIcon* mProxyIcon; - IBOutlet BrowserContentView* mContentView; + IBOutlet BrowserContentView* mContentView; IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource; - IBOutlet HistoryDataSource* mHistoryDataSource; + IBOutlet HistoryDataSource* mHistoryDataSource; - IBOutlet BookmarksToolbar* mPersonalToolbar; + IBOutlet BookmarksToolbar* mPersonalToolbar; IBOutlet NSWindow* mAddBookmarkSheetWindow; IBOutlet NSTextField* mAddBookmarkTitleField; @@ -191,6 +191,8 @@ typedef enum - (void)updateLocationFields:(NSString *)locationString; - (void)updateSiteIcons:(NSImage *)siteIconImage; - (void)updateToolbarItems; +- (void)loadingStarted; +- (void)loadingDone; - (void)focusURLBar; // call to update the image of the lock icon with a value from nsIWebProgressListener @@ -211,9 +213,9 @@ typedef enum - (IBAction)viewSource:(id)aSender; // focussed frame or page - (IBAction)viewPageSource:(id)aSender; // top-level page -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList; -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView; +- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; + - (IBAction)printDocument:(id)aSender; - (IBAction)pageSetup:(id)aSender; - (IBAction)performSearch:(id)aSender; @@ -302,6 +304,7 @@ typedef enum - (IBAction)bookmarkLink: (id)aSender; - (IBAction)copyLinkLocation:(id)aSender; +- (IBAction)copyImage:(id)sender; - (IBAction)copyImageLocation:(id)sender; - (BookmarksToolbar*) bookmarksToolbar; diff --git a/chimera/src/browser/BrowserWindowController.mm b/chimera/src/browser/BrowserWindowController.mm index 979a03ef020..c36add4099a 100644 --- a/chimera/src/browser/BrowserWindowController.mm +++ b/chimera/src/browser/BrowserWindowController.mm @@ -816,6 +816,19 @@ static NSArray* sToolbarDefaults = nil; else return YES; } + +- (void)loadingStarted +{ + [self updateToolbarItems]; + [self startThrobber]; +} + +- (void)loadingDone +{ + [self updateToolbarItems]; + [self stopThrobber]; + [mHistoryDataSource refresh]; +} - (void)updateToolbarItems { @@ -960,16 +973,14 @@ static NSArray* sToolbarDefaults = nil; } } -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView { - [[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView filterList:aFilterList]; + [[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView]; } -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename +- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename { - [[mBrowserView getBrowserView] saveURL: aFilterView filterList: aFilterList - url: aURLSpec suggestedFilename: aFilename]; + [[mBrowserView getBrowserView] saveURL: aFilterView url: aURLSpec suggestedFilename: aFilename]; } - (void)loadSourceOfURL:(NSString*)urlStr @@ -1890,12 +1901,14 @@ static NSArray* sToolbarDefaults = nil; - (IBAction)savePageAs:(id)aSender { - [self saveDocument:NO filterView:nil filterList: nil]; + NSView* accessoryView = [[NSApp delegate] getSavePanelView]; + [self saveDocument:NO filterView:accessoryView]; } - (IBAction)saveFrameAs:(id)aSender { - [self saveDocument:YES filterView:nil filterList: nil]; + NSView* accessoryView = [[NSApp delegate] getSavePanelView]; + [self saveDocument:YES filterView:accessoryView]; } - (IBAction)saveLinkAs:(id)aSender @@ -1915,8 +1928,7 @@ static NSArray* sToolbarDefaults = nil; nsAutoString text; GeckoUtils::GatherTextUnder(mContextMenuNode, text); - [self saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; + [self saveURL:nil url:hrefStr suggestedFilename:[NSString stringWith_nsAString:text]]; } - (IBAction)saveImageAs:(id)aSender @@ -1931,11 +1943,18 @@ static NSArray* sToolbarDefaults = nil; NSString* hrefStr = [NSString stringWith_nsAString: url]; - [self saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; + [self saveURL:nil url:hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; } } +- (IBAction)copyImage:(id)sender +{ + nsCOMPtr webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]); + nsCOMPtr clipboard(do_GetInterface(webBrowser)); + if (clipboard) + clipboard->CopyImageContents(); +} + - (IBAction)copyImageLocation:(id)sender { nsCOMPtr webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]); diff --git a/chimera/src/browser/BrowserWrapper.mm b/chimera/src/browser/BrowserWrapper.mm index c39050967c8..3f1a6120bc2 100644 --- a/chimera/src/browser/BrowserWrapper.mm +++ b/chimera/src/browser/BrowserWrapper.mm @@ -335,10 +335,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged"; mTabTitle = [mLoadingStatusString retain]; [mTabItem setLabel:mTabTitle]; - if (mWindowController) { - [mWindowController updateToolbarItems]; - [mWindowController startThrobber]; - } + if (mWindowController) + [mWindowController loadingStarted]; } - (void)onLoadingCompleted:(BOOL)succeeded @@ -402,10 +400,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged"; [self removeFromSuperview]; } - if (mWindowController) { - [mWindowController updateToolbarItems]; - [mWindowController stopThrobber]; - } + if (mWindowController) + [mWindowController loadingDone]; } - (void)onProgressChange:(int)currentBytes outOf:(int)maxBytes diff --git a/chimera/src/browser/ContentClickListener.mm b/chimera/src/browser/ContentClickListener.mm index bb18dd8fd91..e69de29bb2d 100644 --- a/chimera/src/browser/ContentClickListener.mm +++ b/chimera/src/browser/ContentClickListener.mm @@ -1,147 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * David Hyatt (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import "NSString+Utils.h" - -#include "nsCOMPtr.h" -#include "ContentClickListener.h" -#include "nsIDOMEventTarget.h" -#include "nsIContent.h" -#include "nsIAtom.h" -#include "nsIDOMElement.h" -#include "nsString.h" -#include "nsUnicharUtils.h" -#include "nsIPrefBranch.h" -#include "nsIDOMMouseEvent.h" -#include "nsEmbedAPI.h" -#include "nsIDOMDocument.h" -#include "nsIDOMDocumentEvent.h" -#include "nsIDOMEventTarget.h" -#include "nsIDOMNSHTMLElement.h" -#include "nsIDOMHTMLSelectElement.h" -#include "nsIDOMHTMLOptionElement.h" -#include "nsIDOMHTMLCollection.h" -#include "nsIDOMWindow.h" -#include "nsIScriptGlobalObject.h" -#include "nsIDocument.h" -#include "nsIPresShell.h" -#include "nsIPresContext.h" -#include "nsIFrame.h" -#include "nsIView.h" -#include "nsIWidget.h" -#include "nsIURI.h" -#include "nsIProtocolHandler.h" -#include "nsNetUtil.h" - -// Common helper routines (also used by the context menu code) -#include "GeckoUtils.h" - -#import "CHBrowserView.h" - -NS_IMPL_ISUPPORTS2(ContentClickListener, nsIDOMMouseListener, nsIDOMEventListener); - -ContentClickListener::ContentClickListener(id aBrowserController) -:mBrowserController(aBrowserController) -{ - NS_INIT_ISUPPORTS(); -} - -ContentClickListener::~ContentClickListener() -{ - -} - -NS_IMETHODIMP -ContentClickListener::MouseClick(nsIDOMEvent* aEvent) -{ - nsCOMPtr target; - aEvent->GetTarget(getter_AddRefs(target)); - if (!target) - return NS_OK; - nsCOMPtr content(do_QueryInterface(target)); - - nsCOMPtr linkContent; - nsAutoString href; - GeckoUtils::GetEnclosingLinkElementAndHref(content, getter_AddRefs(linkContent), href); - - // XXXdwh Handle simple XLINKs if we want to be compatible with Mozilla, but who - // really uses these anyway? :) - if (!linkContent || href.IsEmpty()) - return NS_OK; - - nsCOMPtr pref(do_GetService("@mozilla.org/preferences-service;1")); - if (!pref) - return NS_OK; // Something bad happened if we can't get prefs. - - PRUint16 button; - nsCOMPtr mouseEvent(do_QueryInterface(aEvent)); - mouseEvent->GetButton(&button); - - PRBool metaKey, shiftKey, altKey; - mouseEvent->GetMetaKey(&metaKey); - mouseEvent->GetShiftKey(&shiftKey); - mouseEvent->GetAltKey(&altKey); - - NSString* hrefStr = [NSString stringWith_nsAString: href]; - - if ((metaKey && button == 0) || button == 1) { - // The command key is down or we got a middle click. Open the link in a new window or tab. - PRBool useTab; - pref->GetBoolPref("browser.tabs.opentabfor.middleclick", &useTab); - PRBool loadInBackground; - pref->GetBoolPref("browser.tabs.loadInBackground", &loadInBackground); - NSString* referrer = [[[mBrowserController getBrowserWrapper] getBrowserView] getFocusedURLString]; - - if (shiftKey) - loadInBackground = !loadInBackground; - if (useTab && [mBrowserController newTabsAllowed]) - [mBrowserController openNewTabWithURL: hrefStr referrer:referrer loadInBackground: loadInBackground]; - else - [mBrowserController openNewWindowWithURL: hrefStr referrer:referrer loadInBackground: loadInBackground]; - } - else if (altKey) { - // The user wants to save this link. - nsAutoString text; - GeckoUtils::GatherTextUnder(content, text); - - [mBrowserController saveURL: nil filterList: nil - url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]]; - } - - return NS_OK; -} diff --git a/chimera/src/browser/KeychainService.h b/chimera/src/browser/KeychainService.h index 3eeb9018fa1..e69de29bb2d 100644 --- a/chimera/src/browser/KeychainService.h +++ b/chimera/src/browser/KeychainService.h @@ -1,140 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __KeychainService_h__ -#define __KeychainService_h__ - -#include - -#include "CHBrowserView.h" - -#include "nsEmbedAPI.h" -#include "nsIFactory.h" -#include "nsIPrompt.h" -#include "nsIAuthPromptWrapper.h" -#include "nsIObserver.h" -#include "nsIFormSubmitObserver.h" - -class nsIPrefBranch; - -@class CHBrowserView; - -@interface KeychainService : NSObject -{ - BOOL mIsEnabled; - BOOL mIsAutoFillEnabled; - - nsIObserver* mFormSubmitObserver; -} - -+ (KeychainService*) instance; -- (void) shutdown:(id)sender; - -- (BOOL) getUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSMutableString*)username password:(NSMutableString*)pwd item:(KCItemRef*)outItem; -- (BOOL) findUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort; -- (void) storeUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSString*)username password:(NSString*)pwd; -- (void) removeUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort item:(KCItemRef)item; -- (void) updateUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSString*)username password:(NSString*)pwd item:(KCItemRef)item; - -- (void) addListenerToView:(CHBrowserView*)view; - -- (BOOL) isEnabled; -- (BOOL) isAutoFillEnabled; - -@end - -class KeychainPrompt : public nsIAuthPromptWrapper -{ -public: - KeychainPrompt(); - KeychainPrompt(KeychainService*); - virtual ~KeychainPrompt(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIAUTHPROMPT - NS_DECL_NSIAUTHPROMPTWRAPPER - -protected: - - void PreFill(const PRUnichar *, PRUnichar **, PRUnichar **); - void ProcessPrompt(const PRUnichar *, bool, PRUnichar *, PRUnichar *); - static void ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost, PRInt32* outPort); - - nsCOMPtr mPrompt; - KeychainService* mKeychain; -}; - -// -// Keychain form submit observer -// -class KeychainFormSubmitObserver : public nsIObserver, - public nsIFormSubmitObserver -{ -public: - KeychainFormSubmitObserver(KeychainService*); - virtual ~KeychainFormSubmitObserver(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIOBSERVER - - // NS_DECL_NSIFORMSUBMITOBSERVER - NS_IMETHOD Notify(nsIContent* formNode, nsIDOMWindowInternal* window, nsIURI* actionURL, PRBool* cancelSubmit); - -private: - - static BOOL CheckStorePasswordYN(nsIDOMWindowInternal*); - static BOOL CheckChangeDataYN(nsIDOMWindowInternal*); - - static NSWindow* GetNSWindow(nsIDOMWindowInternal* inWindow); - - KeychainService* mKeychain; -}; - -// -// Keychain browser listener to auto fill username/passwords. -// -@interface KeychainBrowserListener : NSObject -{ - KeychainService* mKeychain; - CHBrowserView* mBrowserView; -} - -- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser; - -@end - -#endif diff --git a/chimera/src/browser/KeychainService.mm b/chimera/src/browser/KeychainService.mm index c20a16db4c8..94f514531c6 100644 --- a/chimera/src/browser/KeychainService.mm +++ b/chimera/src/browser/KeychainService.mm @@ -69,6 +69,9 @@ #include "nsIWindowWatcher.h" #include "nsIWebBrowserChrome.h" #include "nsIEmbeddingSiteWindow.h" +#include "nsAppDirectoryServiceDefs.h" + +extern NSString* XPCOMShutDownNotificationName; nsresult @@ -114,7 +117,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // observer service uses a weakref. nsCOMPtr svc = do_GetService("@mozilla.org/observer-service;1"); NS_ASSERTION(svc, "Keychain can't get observer service"); - mFormSubmitObserver = new KeychainFormSubmitObserver(self); + mFormSubmitObserver = new KeychainFormSubmitObserver(); if ( mFormSubmitObserver && svc ) { NS_ADDREF(mFormSubmitObserver); svc->AddObserver(mFormSubmitObserver, NS_FORMSUBMIT_SUBJECT, PR_FALSE); @@ -122,7 +125,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // register for the cocoa notification posted when XPCOM shutdown so we // can unregister the pref callbacks we register below - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:@"XPCOM Shutdown" + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName object:nil]; // cache the values of the prefs and register pref-changed callbacks. Yeah, I know @@ -139,6 +142,10 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) pref->RegisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull); } } + + // load the keychain.nib file with our dialogs in it + BOOL success = [NSBundle loadNibNamed:@"Keychain" owner:self]; + NS_ASSERTION(success, "can't load keychain prompt dialogs"); } return self; } @@ -168,6 +175,8 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) pref->UnregisterCallback(gUseKeychainPref, KeychainPrefChangedCallback, nsnull); pref->UnregisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull); } + + [sInstance release]; } @@ -324,7 +333,181 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused) // - (void) addListenerToView:(CHBrowserView*)view { - [view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:self browser:view] autorelease]]; + [view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:view] autorelease]]; +} + +// +// hitButtonOK: +// hitButtonCancel: +// hitButtonOther: +// +// actions for the buttons of the keychain prompt dialogs. +// + +enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 }; + +- (IBAction)hitButtonOK:(id)sender +{ + [NSApp stopModalWithCode:kOKButton]; +} + +- (IBAction)hitButtonCancel:(id)sender +{ + [NSApp stopModalWithCode:kCancelButton]; +} + +- (IBAction)hitButtonOther:(id)sender +{ + [NSApp stopModalWithCode:kOtherButton]; +} + +// +// confirmStorePassword: +// +// Puts up a dialog when the keychain doesn't yet have an entry from +// this site asking to store it, forget it this once, or mark the site +// on a deny list so we never ask again. +// +- (KeychainPromptResult)confirmStorePassword:(NSWindow*)parent +{ + int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent]; + [confirmStorePasswordPanel close]; + + // the results of hitButtonXX: map to the corresponding values in the + // |KeychainPromptResult| enum so we can just cast and return + return NS_STATIC_CAST(KeychainPromptResult, result); +} + +// +// confirmChangedPassword: +// +// The password stored in the keychain differs from what the user typed +// in. Ask what they want to do to resolve the issue. +// +- (BOOL)confirmChangedPassword:(NSWindow*)parent +{ + int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent]; + [confirmChangePasswordPanel close]; + return (result == kOKButton); +} + + +- (void) addHostToDenyList:(NSString*)host +{ + [[KeychainDenyList instance] addHost:host]; +} + +- (BOOL) isHostInDenyList:(NSString*)host +{ + return [[KeychainDenyList instance] isHostPresent:host]; +} + +@end + + +@interface KeychainDenyList (KeychainDenyListPrivate) +- (NSString*) pathToDenyListFile; +@end + + +@implementation KeychainDenyList + +static KeychainDenyList *sDenyListInstance = nil; + ++ (KeychainDenyList*) instance +{ + return sDenyListInstance ? sDenyListInstance : sDenyListInstance = [[self alloc] init]; +} + +- (id) init +{ + if ( (self = [super init]) ) { + mDenyList = [[NSUnarchiver unarchiveObjectWithFile:[self pathToDenyListFile]] retain]; + if ( !mDenyList ) + mDenyList = [[NSMutableArray alloc] init]; + + mIsDirty = NO; + + // register for the cocoa notification posted when XPCOM shutdown so we + // can release our singleton and flush the file + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName object:nil]; + } + return self; +} + +- (void) dealloc +{ + [self writeToDisk]; + [mDenyList release]; +} + +// +// shutdown: +// +// Called in response to the cocoa notification "XPCOM Shutdown" sent by the cocoa +// browser service before it terminates embedding and shuts down xpcom. Allows us +// to get rid of anything we're holding onto for the length of the app. +// +- (void) shutdown:(id)unused +{ + [sDenyListInstance release]; +} + +// +// writeToDisk +// +// flushes the deny list to the save file in the user's profile, but only +// if it has changed since we read it in. +// +- (void) writeToDisk +{ + if ( mIsDirty ) + [NSArchiver archiveRootObject:mDenyList toFile:[self pathToDenyListFile]]; + mIsDirty = NO; +} + +- (BOOL) isHostPresent:(NSString*)host +{ + return [mDenyList containsObject:host]; +} + +- (void) addHost:(NSString*)host +{ + if ( ![self isHostPresent:host] ) { + [mDenyList addObject:host]; + mIsDirty = YES; + } +} + +- (void) removeHost:(NSString*)host +{ + if ( [self isHostPresent:host] ) { + [mDenyList removeObject:host]; + mIsDirty = YES; + } +} + + +// +// pathToDenyListFile +// +// returns a path ('/' delimited) that cocoa can use to point to the +// deny list save file in the current user's profile +// +- (NSString*) pathToDenyListFile +{ + NSMutableString* path = [[[NSMutableString alloc] init] autorelease]; + + nsCOMPtr appProfileDir; + NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(appProfileDir)); + if ( appProfileDir ) { + nsAutoString profilePath; + appProfileDir->GetPath(profilePath); + [path setString:[NSString stringWith_nsAString:profilePath]]; + [path appendString:@"/Keychain Deny List"]; // |profilePath| is '/' delimited + } + + return path; } @end @@ -338,12 +521,6 @@ NS_IMPL_ISUPPORTS2(KeychainPrompt, nsIAuthPromptWrapper) KeychainPrompt::KeychainPrompt() - : mKeychain([KeychainService instance]) -{ - NS_INIT_ISUPPORTS(); -} - -KeychainPrompt::KeychainPrompt(KeychainService* keychain) : mKeychain(keychain) { NS_INIT_ISUPPORTS(); } @@ -391,7 +568,8 @@ KeychainPrompt::ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost, void KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pwd) { - if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled]) + KeychainService* keychain = [KeychainService instance]; + if(![keychain isEnabled] || ![keychain isAutoFillEnabled]) return; NSString* host = nil; @@ -409,7 +587,7 @@ KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pw // Pre-fill user/password if found in the keychain. // KCItemRef ignore; - if([mKeychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) { + if([keychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) { if ( user ) *user = [username createNewUnicodeBuffer]; if ( pwd ) @@ -427,10 +605,12 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u NSString* username = [NSString stringWithPRUnichars:user]; NSString* password = [NSString stringWithPRUnichars:pwd]; + KeychainService* keychain = [KeychainService instance]; + NSMutableString* origUsername = [NSMutableString string]; NSMutableString* origPwd = [NSMutableString string]; KCItemRef itemRef; - bool found = [mKeychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef]; + bool found = [keychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef]; // // Update, store or remove the user/password depending on the user @@ -438,11 +618,11 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u // keychain. // if(checked && !found) - [mKeychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password]; + [keychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password]; else if(checked && found && (![origUsername isEqualToString:username] || ![origPwd isEqualToString:password])) - [mKeychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef]; + [keychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef]; else if(!checked && found) - [mKeychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef]; + [keychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef]; } // @@ -476,7 +656,7 @@ KeychainPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle, { PreFill(realm, user, pwd); - PRBool checked = [mKeychain isEnabled]; + PRBool checked = [[KeychainService instance] isEnabled]; PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer]; nsresult rv = mPrompt->PromptUsernameAndPassword(dialogTitle, text, user, pwd, checkTitle, &checked, _retval); @@ -501,7 +681,7 @@ KeychainPrompt::PromptPassword(const PRUnichar *dialogTitle, { PreFill(realm, nsnull, pwd); - PRBool checked = [mKeychain isEnabled]; + PRBool checked = [[KeychainService instance] isEnabled]; PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer]; nsresult rv = mPrompt->PromptPassword(dialogTitle, text, pwd, checkTitle, &checked, _retval); @@ -530,7 +710,7 @@ NS_IMPL_ISUPPORTS2(KeychainFormSubmitObserver, nsIObserver, nsIFormSubmitObserver) -KeychainFormSubmitObserver::KeychainFormSubmitObserver(KeychainService* keychain) : mKeychain(keychain) +KeychainFormSubmitObserver::KeychainFormSubmitObserver() { NS_INIT_ISUPPORTS(); //NSLog(@"Keychain form submit observer created."); @@ -551,7 +731,8 @@ NS_IMETHODIMP KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* window, nsIURI* actionURL, PRBool* cancelSubmit) { - if (![mKeychain isEnabled]) + KeychainService* keychain = [KeychainService instance]; + if (![keychain isEnabled]) return NS_OK; nsCOMPtr formNode(do_QueryInterface(node)); @@ -590,25 +771,41 @@ KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* windo docURL->GetHost(host); docURL->GetPort(&port); + // is the host in the deny list? if yes, bail. otherwise check the keychain. + NSString* realm = [NSString stringWithCString:host.get()]; + if ( [keychain isHostInDenyList:realm] ) + return NS_OK; + // // If there's already an entry in the keychain, check if the username // and password match. If not, ask the user what they want to do and replace // it as necessary. If there's no entry, ask if they want to remember it // and then put it into the keychain // - NSString* realm = [NSString stringWithCString:host.get()]; NSString* existingUser = [NSMutableString string]; NSString* existingPassword = [NSMutableString string]; KCItemRef itemRef; - BOOL foundExistingPassword = [mKeychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef]; + BOOL foundExistingPassword = [keychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef]; if ( foundExistingPassword ) { if ( !([existingUser isEqualToString:username] && [existingPassword isEqualToString:password]) ) if ( CheckChangeDataYN(window) ) - [mKeychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef]; + [keychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef]; } else { - if (CheckStorePasswordYN(window)) - [mKeychain storeUsernameAndPassword:realm port:port user:username password:password]; + switch (CheckStorePasswordYN(window)) { + case kSave: + [keychain storeUsernameAndPassword:realm port:port user:username password:password]; + break; + + case kNeverRemember: + // tell the keychain we never want to be prompted about this host again + [keychain addHostToDenyList:realm]; + break; + + case kDontRemember: + // do nothing at all + break; + } } } @@ -644,12 +841,11 @@ KeychainFormSubmitObserver::GetNSWindow(nsIDOMWindowInternal* inWindow) return nswindow; } -BOOL +KeychainPromptResult KeychainFormSubmitObserver::CheckStorePasswordYN(nsIDOMWindowInternal* window) { NSWindow* nswindow = GetNSWindow(window); - nsAlertController* dialog = CHBrowserService::GetAlertController(); - return [dialog confirmStorePassword:nswindow]; + return [[KeychainService instance] confirmStorePassword:nswindow]; } @@ -657,16 +853,14 @@ BOOL KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) { NSWindow* nswindow = GetNSWindow(window); - nsAlertController* dialog = CHBrowserService::GetAlertController(); - return [dialog confirmChangedPassword:nswindow]; + return [[KeychainService instance] confirmChangedPassword:nswindow]; } @implementation KeychainBrowserListener -- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser +- (id)initWithBrowser:(CHBrowserView*)aBrowser { if ( (self = [super init]) ) { - mKeychain = keychain; mBrowserView = aBrowser; } return self; @@ -683,7 +877,8 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) if(!succeeded) return; - if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled]) + KeychainService* keychain = [KeychainService instance]; + if(![keychain isEnabled] || ![keychain isAutoFillEnabled]) return; nsCOMPtr domWin = getter_AddRefs([mBrowserView getContentWindow]); @@ -750,7 +945,7 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window) docURL->GetPort(&port); KCItemRef ignore; - if ([mKeychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) { + if ([keychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) { nsAutoString user, pwd; [username assignTo_nsAString:user]; [password assignTo_nsAString:pwd]; diff --git a/chimera/src/browser/SiteIconProvider.mm b/chimera/src/browser/SiteIconProvider.mm index e6c1709218e..e69de29bb2d 100644 --- a/chimera/src/browser/SiteIconProvider.mm +++ b/chimera/src/browser/SiteIconProvider.mm @@ -1,344 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Chimera code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import "NSString+Utils.h" - -#import "SiteIconProvider.h" - -#include "prtime.h" -#include "nsString.h" -#include "nsISupports.h" -#include "nsNetUtil.h" -#include "nsICacheSession.h" -#include "nsICacheService.h" -#include "nsICacheEntryDescriptor.h" - - -NSString* SiteIconLoadNotificationName = @"siteicon_load_notification"; -NSString* SiteIconLoadImageKey = @"siteicon_load_image"; -NSString* SiteIconLoadURIKey = @"siteicon_load_uri"; -NSString* SiteIconLoadUserDataKey = @"siteicon_load_user_data"; - - -static inline PRUint32 PRTimeToSeconds(PRTime t_usec) -{ - PRTime usec_per_sec; - PRUint32 t_sec; - LL_I2L(usec_per_sec, PR_USEC_PER_SEC); - LL_DIV(t_usec, t_usec, usec_per_sec); - LL_L2I(t_sec, t_usec); - return t_sec; -} - -class NeckoCacheHelper -{ -public: - - NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue); - ~NeckoCacheHelper() {} - - nsresult Init(const char* inCacheSessionName); - nsresult ExistsInCache(const nsACString& inURI, PRBool* outExists); - nsresult PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds); - - nsresult ClearCache(); - -protected: - - const char* mMetaElement; - const char* mMetaValue; - nsCOMPtr mCacheSession; - -}; - -static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID); - -NeckoCacheHelper::NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue) -: mMetaElement(inMetaElement) -, mMetaValue(inMetaValue) -{ -} - -nsresult NeckoCacheHelper::Init(const char* inCacheSessionName) -{ - nsresult rv; - - nsCOMPtr cacheService = do_GetService(kCacheServiceCID, &rv); - if (NS_FAILED(rv)) - return rv; - - rv = cacheService->CreateSession(inCacheSessionName, - nsICache::STORE_ANYWHERE, nsICache::STREAM_BASED, - getter_AddRefs(mCacheSession)); - if (NS_FAILED(rv)) - return rv; - - return NS_OK; -} - - -nsresult NeckoCacheHelper::ExistsInCache(const nsACString& inURI, PRBool* outExists) -{ - NS_ASSERTION(mCacheSession, "No cache session"); - - nsCOMPtr entryDesc; - nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc)); - - *outExists = NS_SUCCEEDED(rv) && (entryDesc != NULL); - return NS_OK; -} - -nsresult NeckoCacheHelper::PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds) -{ - NS_ASSERTION(mCacheSession, "No cache session"); - - nsCOMPtr entryDesc; - nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_WRITE, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc)); - if (NS_FAILED(rv) || !entryDesc) return rv; - - nsCacheAccessMode accessMode; - rv = entryDesc->GetAccessGranted(&accessMode); - if (NS_FAILED(rv)) - return rv; - - if (accessMode != nsICache::ACCESS_WRITE) - return NS_ERROR_FAILURE; - - entryDesc->SetMetaDataElement(mMetaElement, mMetaValue); // just set a bit of meta data. - entryDesc->SetExpirationTime(PRTimeToSeconds(PR_Now()) + inExpirationTimeSeconds); - - entryDesc->MarkValid(); - entryDesc->Close(); - - return NS_OK; -} - -nsresult NeckoCacheHelper::ClearCache() -{ - NS_ASSERTION(mCacheSession, "No cache session"); - - return mCacheSession->EvictEntries(); -} - - -#pragma mark - - -static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& outFaviconURI) -{ - outFaviconURI.Truncate(0); - - nsCOMPtr uri; - nsresult rv = NS_NewURI(getter_AddRefs(uri), inURIString); - if (NS_FAILED(rv)) - return rv; - - // check for http/https - PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE; - uri->SchemeIs("http", &isHTTP); - uri->SchemeIs("https", &isHTTPS); - if (!isHTTP && !isHTTPS) - return NS_OK; - - PRInt32 port; - uri->GetPort(&port); - - nsCAutoString scheme; - uri->GetScheme(scheme); - - nsCAutoString host; - uri->GetHost(host); - - nsCAutoString faviconURI(scheme); - faviconURI.Append("://"); - faviconURI.Append(host); - if (port != -1) { - faviconURI.Append(':'); - faviconURI.AppendInt(port); - } - faviconURI.Append("/favicon.ico"); - - outFaviconURI.Assign(NS_ConvertUTF8toUCS2(faviconURI)); - return NS_OK; -} - - -@interface SiteIconProvider(Private) - -- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds; -- (BOOL)inMissedIconsCache:(const nsAString&)inURI; - -@end - - -@implementation SiteIconProvider - -- (id)init -{ - if ((self = [super init])) - { - mMissedIconsCacheHelper = new NeckoCacheHelper("Favicon", "Missed"); - nsresult rv = mMissedIconsCacheHelper->Init("MissedIconsCache"); - if (NS_FAILED(rv)) { - delete mMissedIconsCacheHelper; - mMissedIconsCacheHelper = NULL; - } - } - - return self; -} - -- (void)dealloc -{ - delete mMissedIconsCacheHelper; - [super dealloc]; -} - -- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds -{ - if (mMissedIconsCacheHelper) - { - nsresult rv = mMissedIconsCacheHelper->PutInCache(NS_ConvertUCS2toUTF8(inURI), inExpSeconds); - } - -} - -- (BOOL)inMissedIconsCache:(const nsAString&)inURI -{ - PRBool inCache = PR_FALSE; - - if (mMissedIconsCacheHelper) - mMissedIconsCacheHelper->ExistsInCache(NS_ConvertUCS2toUTF8(inURI), &inCache); - - return inCache; -} - -- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork -{ - // look for a favicon - nsAutoString uriString; - [inURI assignTo_nsAString:uriString]; - - nsAutoString faviconURIString; - MakeFaviconURIFromURI(uriString, faviconURIString); - if (faviconURIString.Length() == 0) - return NO; - - NSString* faviconString = [NSString stringWith_nsAString:faviconURIString]; - - // is this uri already in the missing icons cache? - if ([self inMissedIconsCache:faviconURIString]) - { - return NO; - } - - RemoteDataProvider* dataProvider = [RemoteDataProvider sharedRemoteDataProvider]; - return [dataProvider loadURI:faviconString forTarget:sender withListener:self withUserData:userData allowNetworking:inAllowNetwork]; -} - -#define SITE_ICON_EXPIRATION_SECONDS (60 * 60 * 24 * 7) // 1 week - -// this is called on the main thread -- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status -{ - nsAutoString uriString; - [inURI assignTo_nsAString:uriString]; - - BOOL loadOK = NS_SUCCEEDED(status) && (data != nil); - - // it's hard to tell if the favicon load succeeded or not. Even if the file - // does not exist, servers will send back a 404 page with a 0 status. - // So we just go ahead and try to make the image; it will return nil on - // failure. - NSImage* faviconImage = nil; - - NS_DURING - faviconImage = [[NSImage alloc] initWithData:data]; - NS_HANDLER - NSLog(@"Exception \"%@ making\" favicon image for %@", localException, inURI); - faviconImage = nil; - NS_ENDHANDLER - - BOOL gotImageData = loadOK && (faviconImage != nil); - if (NS_SUCCEEDED(status) && !gotImageData) // error status indicates that load was attempted from cache - { - [self addToMissedIconsCache:uriString withExpirationSeconds:SITE_ICON_EXPIRATION_SECONDS]; - } - - if (gotImageData) - { - [faviconImage setDataRetained:YES]; - [faviconImage setScalesWhenResized:YES]; - [faviconImage setSize:NSMakeSize(16, 16)]; - } - - // we always send out the notification, so that clients know - // about failed requests - NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys: - inURI, SiteIconLoadURIKey, - faviconImage, SiteIconLoadImageKey, // may be nil - userData, SiteIconLoadUserDataKey, - nil]; - - [[NSNotificationCenter defaultCenter] postNotificationName: SiteIconLoadNotificationName - object:target userInfo:notificationData]; -} - -#pragma mark - - -+ (SiteIconProvider*)sharedFavoriteIconProvider -{ - static SiteIconProvider* sIconProvider = nil; - if (!sIconProvider) - { - sIconProvider = [[SiteIconProvider alloc] init]; - } - - return sIconProvider; -} - - -+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI -{ - nsAutoString uriString; - [inURI assignTo_nsAString:uriString]; - - nsAutoString faviconURIString; - MakeFaviconURIFromURI(uriString, faviconURIString); - return [NSString stringWith_nsAString:faviconURIString]; -} - -@end diff --git a/chimera/src/browser/nsAlertController.h b/chimera/src/browser/nsAlertController.h index 1790fc2054d..91bdc274498 100644 --- a/chimera/src/browser/nsAlertController.h +++ b/chimera/src/browser/nsAlertController.h @@ -53,8 +53,6 @@ IBOutlet id confirmPanelText; IBOutlet id confirmPanelButton1; IBOutlet id confirmPanelButton2; - IBOutlet id confirmStorePasswordPanel; - IBOutlet id confirmChangePasswordPanel; IBOutlet id promptPanel; IBOutlet id promptPanelCheck; IBOutlet id promptPanelText; @@ -90,8 +88,6 @@ - (int)confirmCheckEx:(NSWindow*)parent title:(NSString*)title text:(NSString*)text button1:(NSString*)btn1 button2:(NSString*)btn2 button3:(NSString*)btn3 checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue; -- (BOOL)confirmStorePassword:(NSWindow*)parent; -- (BOOL)confirmChangedPassword:(NSWindow*)parent; - (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck; - (BOOL)promptUserNameAndPassword:(NSWindow*)parent title:(NSString*)title text:(NSString*)text userNameText:(NSMutableString*)userNameText passwordText:(NSMutableString*)passwordText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck; diff --git a/chimera/src/browser/nsAlertController.mm b/chimera/src/browser/nsAlertController.mm index 8f1ac58cd80..326878cc28d 100644 --- a/chimera/src/browser/nsAlertController.mm +++ b/chimera/src/browser/nsAlertController.mm @@ -154,19 +154,6 @@ enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 }; return result; } -- (BOOL)confirmStorePassword:(NSWindow*)parent -{ - int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent]; - [confirmStorePasswordPanel close]; - return (result == kOKButton); -} - -- (BOOL)confirmChangedPassword:(NSWindow*)parent -{ - int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent]; - [confirmChangePasswordPanel close]; - return (result == kOKButton); -} - (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck { diff --git a/chimera/src/download/ProgressDlgController.h b/chimera/src/download/ProgressDlgController.h index 3b1b3a3a861..e69de29bb2d 100644 --- a/chimera/src/download/ProgressDlgController.h +++ b/chimera/src/download/ProgressDlgController.h @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import - -#import "CHDownloadProgressDisplay.h" - -#include "nscore.h" - -class nsIWebBrowserPersist; -class nsISupports; -class nsIInputStream; -class nsDownloadListener; - - -@interface ChimeraDownloadControllerFactory : DownloadControllerFactory -@end - - -@interface ProgressDlgController : NSWindowController -{ - IBOutlet NSTextField *mElapsedTimeLabel; - IBOutlet NSTextField *mFromField; - IBOutlet NSTextField *mStatusLabel; - IBOutlet NSTextField *mTimeLeftLabel; - IBOutlet NSTextField *mToField; - IBOutlet NSProgressIndicator *mProgressBar; - - NSToolbarItem *leaveOpenToggleToolbarItem; - - BOOL mSaveFileDialogShouldStayOpen; - BOOL mDoingAutoFileDownload; - BOOL mIsFileSave; - BOOL mDownloadIsComplete; - long mCurrentProgress; // if progress bar is indeterminate, can still calc stats. - - CHDownloader *mDownloader; // we hold a ref to this - NSTimer *mDownloadTimer; -} - -+ (int)numDownloadInProgress; - --(void)autosaveWindowFrame; - --(void) setupDownloadTimer; --(void) killDownloadTimer; --(void) setDownloadProgress:(NSTimer *)aTimer; --(NSString *) formatTime:(int)aSeconds; --(NSString *) formatFuzzyTime:(int)aSeconds; --(NSString *) formatBytes:(float)aBytes; - -@end diff --git a/chimera/src/download/ProgressDlgController.mm b/chimera/src/download/ProgressDlgController.mm index f602e492d4c..9ce24f3576a 100644 --- a/chimera/src/download/ProgressDlgController.mm +++ b/chimera/src/download/ProgressDlgController.mm @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -35,504 +36,319 @@ * * ***** END LICENSE BLOCK ***** */ +#import "NSView+Utils.h" + #import "ProgressDlgController.h" -#include "nsCOMPtr.h" -#include "nsString.h" -#include "nsCRT.h" -#include "nsIWebBrowserPersist.h" -#include "nsIInputStream.h" -#include "nsIURL.h" -#include "nsILocalFile.h" -#include "nsIDOMHTMLDocument.h" -#include "nsIWebProgressListener.h" -#include "nsIDownload.h" -#include "nsIComponentManager.h" -#include "nsIPref.h" - -static NSString *SaveFileToolbarIdentifier = @"Save File Dialog Toolbar"; -static NSString *CancelToolbarItemIdentifier = @"Cancel Toolbar Item"; -static NSString *ShowFileToolbarItemIdentifier = @"Show File Toolbar Item"; -static NSString *OpenFileToolbarItemIdentifier = @"Open File Toolbar Item"; -static NSString *LeaveOpenToolbarItemIdentifier = @"Leave Open Toggle Toolbar Item"; +#import "ProgressViewController.h" +#import "PreferenceManager.h" static NSString *ProgressWindowFrameSaveName = @"ProgressWindow"; -@implementation ChimeraDownloadControllerFactory : DownloadControllerFactory -- (NSWindowController *)createDownloadController -{ - NSWindowController* progressController = [[ProgressDlgController alloc] initWithWindowNibName: @"ProgressDialog"]; - NSAssert([progressController conformsToProtocol:@protocol(CHDownloadProgressDisplay)], - @"progressController should conform to CHDownloadProgressDisplay protocol"); - return progressController; -} + +@interface ProgressDlgController(PrivateProgressDlgController) + +- (void)resizeWindowToFit; +- (void)rebuildViews; +- (NSSize)windowSizeForStackSize:(NSSize)stackSize; @end -#pragma mark - -@interface ProgressDlgController(Private) --(void)setupToolbar; -@end - @implementation ProgressDlgController -static int gNumActiveDownloads = 0; +static id gSharedProgressController = nil; -+ (int)numDownloadInProgress ++ (ProgressDlgController *)sharedDownloadController; { - return gNumActiveDownloads; + if (gSharedProgressController == nil) + gSharedProgressController = [[ProgressDlgController alloc] init]; + + return gSharedProgressController; +} + +- (id)init +{ + if ((self == [super initWithWindowNibName:@"ProgressDialog"])) + { + // Register for notifications when the stack view changes size + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(stackViewResized:) + name:StackViewResizedNotificationName + object:nil]; + + mProgressViewControllers = [[NSMutableArray alloc] init]; + + mDefaultWindowSize = [[self window] frame].size; + // it would be nice if we could get the frame from the name, and then + // mess with it before setting it. + [[self window] setFrameUsingName:ProgressWindowFrameSaveName]; + // set the window to its default height + NSRect windowFrame = [[self window] frame]; + windowFrame.size.height = mDefaultWindowSize.height; + [[self window] setFrame:windowFrame display:NO]; + + // We provide the views for the stack view, from mProgressViewControllers + [mStackView setDataSource:self]; + + [mScrollView setDrawsBackground:NO]; + [mNoDownloadsText retain]; // so we can remove it from its superview + } + + return self; } - (void)dealloc { - // if we get here because we're quitting, the listener will still be alive - // yet we're going away. As a result, we need to tell the d/l listener to - // forget it ever met us and necko will clean it up on its own. - if ( mDownloader) - mDownloader->DetachDownloadDisplay(); - NS_IF_RELEASE(mDownloader); + if (self == gSharedProgressController) + gSharedProgressController = nil; + + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [mProgressViewControllers release]; + [mNoDownloadsText release]; + [self killDownloadTimer]; [super dealloc]; } -- (void)windowDidLoad +- (void)didStartDownload:(id )progressDisplay { - [super windowDidLoad]; - - mDownloadIsComplete = NO; - mDoingAutoFileDownload = NO; + [self showWindow:nil]; // make sure the window is visible - if (!mIsFileSave) { - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - PRBool save = PR_FALSE; - prefs->GetBoolPref("browser.download.progressDnldDialog.keepAlive", &save); - mSaveFileDialogShouldStayOpen = save; - - PRBool autoHelperDispatch = PR_FALSE; - prefs->GetBoolPref("browser.download.autoDispatch", &autoHelperDispatch); - mDoingAutoFileDownload = autoHelperDispatch; + [self rebuildViews]; + [self setupDownloadTimer]; +} + +- (void)didEndDownload:(id )progressDisplay +{ + [self rebuildViews]; // to swap in the completed view +} + +- (void)removeDownload:(id )progressDisplay +{ + [mProgressViewControllers removeObject:progressDisplay]; + + if ([mProgressViewControllers count] == 0) + { + // Stop doing stuff if there aren't any downloads going on + [self killDownloadTimer]; } - [self setupToolbar]; - [mProgressBar setUsesThreadedAnimation:YES]; - [mProgressBar startAnimation:self]; // move to onStateChange + [self rebuildViews]; } -- (void)setupToolbar +- (void)stackViewResized:(NSNotification *)notification { - NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:SaveFileToolbarIdentifier] autorelease]; - - [toolbar setDisplayMode:NSToolbarDisplayModeDefault]; - [toolbar setAllowsUserCustomization:YES]; - [toolbar setAutosavesConfiguration:YES]; - [toolbar setDelegate:self]; - [[self window] setToolbar:toolbar]; + NSDictionary* userInfo = [notification userInfo]; + NSSize oldStackSize = [[userInfo objectForKey:@"oldsize"] sizeValue]; + + // this code is used to auto-resize the downloads window when + // its contents change size, if the window is in its standard, "zoomed" + // state. This allows the user to choose between auto-resizing behavior, + // by leaving the window alone, or their own size, by resizing it. + + // get the size the window would have been if it had been in the + // standard state, given the old size of the contents + NSSize oldZoomedWindowSize = [self windowSizeForStackSize:oldStackSize]; + NSSize curWindowSize = [[self window] frame].size; + + // only resize if the window matches the stack size + if (CHCloseSizes(oldZoomedWindowSize, curWindowSize, 4.0)) + [self resizeWindowToFit]; } -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar +// given the dimensions of our stack view, return the dimensions of the window, +// assuming the window is zoomed to show as much of the contents as possible. +- (NSSize)windowSizeForStackSize:(NSSize)stackSize { - return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, - ShowFileToolbarItemIdentifier, - OpenFileToolbarItemIdentifier, - LeaveOpenToolbarItemIdentifier, - NSToolbarCustomizeToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - NSToolbarSpaceItemIdentifier, - NSToolbarSeparatorItemIdentifier, - nil]; + NSSize actualScrollFrame = [mScrollView frame].size; + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:stackSize + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; + + // frameSizeForContentSize seems to return a width 1 pixel too narrow + scrollFrameSize.width += 1; + + NSRect contentRect = [[[self window] contentView] frame]; + contentRect.size.width += scrollFrameSize.width - actualScrollFrame.width; + contentRect.size.height += scrollFrameSize.height - actualScrollFrame.height; + contentRect.origin = [[self window] convertBaseToScreen:contentRect.origin]; // convert to screen + + NSRect advisoryWindowFrame = [NSWindow frameRectForContentRect:contentRect styleMask:[[self window] styleMask]]; + NSRect constrainedRect = [[self window] constrainFrameRect:advisoryWindowFrame toScreen:[[self window] screen]]; + return constrainedRect.size; } -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar +- (void)resizeWindowToFit { - return [NSArray arrayWithObjects: CancelToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - LeaveOpenToolbarItemIdentifier, - NSToolbarFlexibleSpaceItemIdentifier, - ShowFileToolbarItemIdentifier, - OpenFileToolbarItemIdentifier, - nil]; + if ([mProgressViewControllers count] > 0) + { + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; + NSSize curScrollFrameSize = [mScrollView frame].size; + + NSRect windowFrame = [[self window] frame]; + + float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height); + windowFrame.size.height += frameDelta; + windowFrame.origin.y -= frameDelta; // maintain top + + [[self window] setFrame:windowFrame display:YES]; + } } -- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem +- (void)rebuildViews { - if ([toolbarItem action] == @selector(cancel)) // cancel button - return (!mDownloadIsComplete); - if ([toolbarItem action] == @selector(pauseAndResumeDownload)) // pause/resume button - return (NO); // Hey - it hasn't been hooked up yet. !mDownloadIsComplete when it is. - if ([toolbarItem action] == @selector(showFile)) // show file - return (mDownloadIsComplete); - if ([toolbarItem action] == @selector(openFile)) // open file - return (mDownloadIsComplete); - return YES; // turn it on otherwise. + [mStackView reloadSubviews]; + + if ([mProgressViewControllers count] == 0) + { + [[[self window] contentView] addSubview:mNoDownloadsText]; + } + else + { + [mNoDownloadsText removeFromSuperview]; + } + +} + +- (int)numDownloadsInProgress +{ + unsigned int numViews = [mProgressViewControllers count]; + int numActive = 0; + + for (unsigned int i = 0; i < numViews; i++) + { + if ([[mProgressViewControllers objectAtIndex:i] isActive]) + ++numActive; + } + return numActive; } -(void)autosaveWindowFrame { - [[self window] saveFrameUsingName: ProgressWindowFrameSaveName]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar - itemForItemIdentifier:(NSString *)itemIdent - willBeInsertedIntoToolbar:(BOOL)willBeInserted -{ - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease]; - - if ( [itemIdent isEqual:CancelToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Cancel",@"Cancel")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"CancelPaletteLabel",@"Cancel Download")]; - [toolbarItem setToolTip:NSLocalizedString(@"CancelToolTip",@"Cancel this file download")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveCancel"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(cancel)]; - } - else if ( [itemIdent isEqual:ShowFileToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Show File",@"Show File")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Show File",@"Show File")]; - [toolbarItem setToolTip:NSLocalizedString(@"ShowToolTip",@"Show the saved file in the Finder")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveShowFile"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(showFile)]; - } - else if ( [itemIdent isEqual:OpenFileToolbarItemIdentifier] ) - { - [toolbarItem setLabel:NSLocalizedString(@"Open File",@"Open File")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Open File",@"Open File")]; - [toolbarItem setToolTip:NSLocalizedString(@"OpenToolTip",@"Open the saved file in its default application.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveOpenFile"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(openFile)]; - } - else if ( [itemIdent isEqual:LeaveOpenToolbarItemIdentifier] ) - { - if ( !mIsFileSave && !mDoingAutoFileDownload ) - { - if ( mSaveFileDialogShouldStayOpen ) - { - [toolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [toolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(toggleLeaveOpen)]; - } - else - { - [toolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")]; - [toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [toolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")]; - [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; - [toolbarItem setTarget:self]; - [toolbarItem setAction:@selector(toggleLeaveOpen)]; - } - if ( willBeInserted ) - { - leaveOpenToggleToolbarItem = toolbarItem; //establish reference - } - } - } else - { - toolbarItem = nil; - } - - return toolbarItem; -} - --(void)cancel -{ - if (mDownloader) // we should always have one - mDownloader->CancelDownload(); - - // clean up downloaded file. - do it here on in CancelDownload? - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSString *thePath = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([fileManager isDeletableFileAtPath:thePath]) - // if we delete it, fantastic. if not, oh well. better to move to trash instead? - [fileManager removeFileAtPath:thePath handler:nil]; - - // we can _not_ set the |mDownloadIsComplete| flag here because the download really - // isn't done yet. We'll probably continue to process more PLEvents that are already - // in the queue until we get a STATE_STOP state change. As a result, we just keep - // going until that comes in (and it will, because we called CancelDownload() above). - // Ensure that the window goes away when we get there by flipping the 'stay alive' - // flag. (bug 154913) - mSaveFileDialogShouldStayOpen = NO; -} - --(void)showFile -{ - NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([[NSWorkspace sharedWorkspace] selectFile:theFile - inFileViewerRootedAtPath:[theFile stringByDeletingLastPathComponent]]) - return; - // hmmm. it didn't work. that's odd. need localized error messages. for now, just beep. - NSBeep(); -} - --(void)openFile -{ - NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath]; - if ([[NSWorkspace sharedWorkspace] openFile:theFile]) - return; - // hmmm. it didn't work. that's odd. need localized error message. for now, just beep. - NSBeep(); - -} - --(void)toggleLeaveOpen -{ - if ( ! mSaveFileDialogShouldStayOpen ) { - mSaveFileDialogShouldStayOpen = YES; - [leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")]; - [leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")]; - [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]]; - } else { - mSaveFileDialogShouldStayOpen = NO; - [leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")]; - [leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")]; - [leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")]; - [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]]; - } - - nsCOMPtr prefs(do_GetService(NS_PREF_CONTRACTID)); - prefs->SetBoolPref("browser.download.progressDnldDialog.keepAlive", mSaveFileDialogShouldStayOpen); + [[self window] saveFrameUsingName:ProgressWindowFrameSaveName]; } - (void)windowWillClose:(NSNotification *)notification { [self autosaveWindowFrame]; - [self autorelease]; -} - -- (BOOL)windowShouldClose:(NSNotification *)notification -{ - [self killDownloadTimer]; - if (!mDownloadIsComplete) { //whoops. hard cancel. - [self cancel]; - return NO; // let setDownloadProgress handle the close. - } - return YES; } - (void)killDownloadTimer { - if (mDownloadTimer) { + if (mDownloadTimer) + { [mDownloadTimer invalidate]; [mDownloadTimer release]; mDownloadTimer = nil; - } + } } + - (void)setupDownloadTimer { [self killDownloadTimer]; - mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 - target:self - selector:@selector(setDownloadProgress:) - userInfo:nil - repeats:YES] retain]; -} - --(NSString *)formatTime:(int)seconds -{ - NSMutableString *theTime =[[[NSMutableString alloc] initWithCapacity:8] autorelease]; - [theTime setString:@""]; - NSString *padZero = [NSString stringWithString:@"0"]; - //write out new elapsed time - if (seconds >= 3600){ - [theTime appendFormat:@"%d:",(seconds / 3600)]; - seconds = seconds % 3600; - } - NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)]; - if ([elapsedMin length] == 2) - [theTime appendString:[padZero stringByAppendingString:elapsedMin]]; - else - [theTime appendString:elapsedMin]; - seconds = seconds % 60; - NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds]; - if ([elapsedSec length] == 2) - [theTime appendString:elapsedSec]; - else - [theTime appendString:[padZero stringByAppendingString:elapsedSec]]; - return theTime; -} -// fuzzy time gives back strings like "about 5 seconds" --(NSString *)formatFuzzyTime:(int)seconds -{ - // check for seconds first - if (seconds < 60) { - if (seconds < 7) - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),5] autorelease]; - if (seconds < 13) - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),10] autorelease]; - return [[[NSString alloc] initWithString:NSLocalizedString(@"UnderMin",@"Under a minute")] autorelease]; - } - // seconds becomes minutes and we keep checking. - seconds = seconds/60; - if (seconds < 60) { - if (seconds < 2) - return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutMin",@"About a minute")] autorelease]; - // OK, tell the good people how much time we have left. - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"),seconds] autorelease]; - } - //this download will never seemingly never end. now seconds become hours. - seconds = seconds/60; - if (seconds < 2) - return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutHour",@"Over an hour")] autorelease]; - return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutHours",@"Over %d hours"),seconds] autorelease]; -} - - --(NSString *)formatBytes:(float)bytes -{ // this is simpler than my first try. I peaked at Omnigroup byte formatting code. - // if bytes are negative, we return question marks. - if (bytes < 0) - return [[[NSString alloc] initWithString:@"???"] autorelease]; - // bytes first. - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f bytes",bytes] autorelease]; - // kb - bytes = bytes/1024; - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f KB",bytes] autorelease]; - // mb - bytes = bytes/1024; - if (bytes < 1024) - return [[[NSString alloc] initWithFormat:@"%.1f MB",bytes] autorelease]; - // gb - bytes = bytes/1024; - return [[[NSString alloc] initWithFormat:@"%.1f GB",bytes] autorelease]; -} - -// this handles lots of things. -- (void)setDownloadProgress:(NSTimer *)downloadTimer; -{ - // XXX this logic needs cleaning up. - // Ack! we're closing the window with the download still running! - if (mDownloadIsComplete) + mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 + target:self + selector:@selector(setDownloadProgress:) + userInfo:nil + repeats:YES] retain]; +} + +// Called by our timer to refresh all the download stats +- (void)setDownloadProgress:(NSTimer *)aTimer +{ + [mProgressViewControllers makeObjectsPerformSelector:@selector(refreshDownloadInfo)]; + // if the window is minimized, we want to update the dock image here. But how? +} + +- (NSApplicationTerminateReply)allowTerminate +{ + if ([self numDownloadsInProgress] > 0) { - [[self window] performClose:self]; - return; + // make sure the window is visible + [self showWindow:self]; + + NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?"); + NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @""); + NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel"); + NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit"); + + // while the panel is up, download dialogs won't update (no timers firing) but + // downloads continue (PLEvents being processed) + id panel = NSGetAlertPanel(alert, message, okButton, altButton, nil, message); + + [NSApp beginSheet:panel + modalForWindow:[self window] + modalDelegate:self + didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) + contextInfo:NULL]; + int sheetResult = [NSApp runModalForWindow: panel]; + [NSApp endSheet: panel]; + [panel orderOut: self]; + NSReleaseAlertPanel(panel); + + return (sheetResult == NSAlertDefaultReturn) ? NSTerminateCancel : NSTerminateNow; } - // get the elapsed time - NSArray *elapsedTimeArray = [[mElapsedTimeLabel stringValue] componentsSeparatedByString:@":"]; - int j = [elapsedTimeArray count]; - int elapsedSec = [[elapsedTimeArray objectAtIndex:(j-1)] intValue] + [[elapsedTimeArray objectAtIndex:(j-2)] intValue]*60; - if (j==3) // this download is taking forever. - elapsedSec += [[elapsedTimeArray objectAtIndex:0] intValue]*3600; - // update elapsed time - [mElapsedTimeLabel setStringValue:[self formatTime:(++elapsedSec)]]; - // for status field & time left - float maxBytes = ([mProgressBar maxValue]); - float byteSec = mCurrentProgress/elapsedSec; - // OK - if downloadTimer is nil, we're done - fix maxBytes value for status report. - if (!downloadTimer) - maxBytes = mCurrentProgress; - // update status field - NSString *labelString = NSLocalizedString(@"LabelString",@"%@ of %@ total (at %@/sec)"); - [mStatusLabel setStringValue: [NSString stringWithFormat:labelString, [self formatBytes:mCurrentProgress], [self formatBytes:maxBytes], [self formatBytes:byteSec]]]; - // updating estimated time left field - // if maxBytes < 0, can't calc time left. - // if !downloadTimer, download is finished. either way, make sure time left is 0. - if ((maxBytes > 0) && (downloadTimer)) - { - int secToGo = (int)ceil((elapsedSec*maxBytes/mCurrentProgress) - elapsedSec); - [mTimeLeftLabel setStringValue:[self formatFuzzyTime:secToGo]]; - } - else if (!downloadTimer) - { // download done. Set remaining time to 0, fix progress bar & cancel button - mDownloadIsComplete = YES; // all done. we got a STATE_STOP - [mTimeLeftLabel setStringValue:@""]; - [self setProgressTo:mCurrentProgress ofMax:mCurrentProgress]; - if (!mSaveFileDialogShouldStayOpen || mDoingAutoFileDownload) - [[self window] performClose:self]; // close window - else - [[self window] update]; // redraw window - } - else //maxBytes is undetermined. Set remaining time to question marks. - [mTimeLeftLabel setStringValue:@"???"]; + + return NSTerminateNow; +} + +- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + [NSApp stopModalWithCode:returnCode]; } #pragma mark - -// CHDownloadProgressDisplay protocol methods - -- (void)onStartDownload:(BOOL)isFileSave; +// implement to zoom to a size that just fits the contents +- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame { - mIsFileSave = isFileSave; + NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size + hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder]; - [self window]; // make the window - [[self window] setFrameUsingName: ProgressWindowFrameSaveName]; + NSSize curScrollFrameSize = [mScrollView frame].size; + float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height); - [self showWindow: self]; - [self setupDownloadTimer]; - - gNumActiveDownloads++; + NSRect windowFrame = [[self window] frame]; + windowFrame.size.height += frameDelta; + windowFrame.origin.y -= frameDelta; // maintain top + + windowFrame.size.width = mDefaultWindowSize.width; + // cocoa will ensure that the window fits onscreen for us + return windowFrame; } -- (void)onEndDownload +#pragma mark - + +/* + CHStackView datasource methods +*/ + +- (int)subviewsForStackView:(CHStackView *)stackView { - gNumActiveDownloads --; + return [mProgressViewControllers count]; +} + +- (NSView *)viewForStackView:(CHStackView *)aResizingView atIndex:(int)index +{ + return [[mProgressViewControllers objectAtIndex:index] view]; +} + +#pragma mark - + +/* + Just create a progress view, but don't display it (otherwise the URL fields etc. + are just blank) +*/ +- (id )createProgressDisplay +{ + ProgressViewController *newController = [[ProgressViewController alloc] init]; + [newController setProgressWindowController:self]; + [mProgressViewControllers addObject:newController]; - // if we're quitting, our progress window is already gone and we're in the - // process of shutting down gecko and all the d/l listeners. The timer, at - // that point, is the only thing keeping us alive. Killing it will cause - // us to go away immediately, so kung-fu deathgrip it until we're done twiddling - // bits on ourself. - [self retain]; // Enter The Dragon! - [self killDownloadTimer]; - [self setDownloadProgress:nil]; - [self release]; -} - -- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress -{ - mCurrentProgress = aCurProgress; // fall back for stat calcs - - if (![mProgressBar isIndeterminate]) //most likely - just update value - { - if (aCurProgress == aMaxProgress) //handles little bug in FTP download size - [mProgressBar setMaxValue:aMaxProgress]; - - [mProgressBar setDoubleValue:aCurProgress]; - } - else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values - { - [mProgressBar setIndeterminate:NO]; - [mProgressBar setMaxValue:aMaxProgress]; - [mProgressBar setDoubleValue:aCurProgress]; - } // if neither case was true, it's barber pole city. -} - --(void) setDownloadListener: (CHDownloader*)aDownloader -{ - if (mDownloader != aDownloader) - NS_IF_RELEASE(mDownloader); - - NS_IF_ADDREF(mDownloader = aDownloader); -} - -- (void)setSourceURL:(NSString*)aSourceURL -{ - [mFromField setStringValue: aSourceURL]; - [mFromField display]; // force an immmeditate update -} - -- (void)setDestinationPath:(NSString*)aDestPath -{ - [mToField setStringValue: [aDestPath stringByAbbreviatingWithTildeInPath]]; - [mToField display]; // force an immmeditate update - - // also set the window title - NSString* downloadFileName = [aDestPath lastPathComponent]; - if ([downloadFileName length] == 0) - downloadFileName = aDestPath; - - [[self window] setTitle:[NSString stringWithFormat:NSLocalizedString(@"DownloadingTitle", @""), downloadFileName]]; + return newController; } @end diff --git a/chimera/src/download/ProgressViewController.h b/chimera/src/download/ProgressViewController.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/src/download/ProgressViewController.mm b/chimera/src/download/ProgressViewController.mm new file mode 100644 index 00000000000..86f5fb302db --- /dev/null +++ b/chimera/src/download/ProgressViewController.mm @@ -0,0 +1,544 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2002 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Calum Robinson + * Simon Fraser + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#import "NSView+Utils.h" + +#import "ProgressViewController.h" +#import "ProgressDlgController.h" +#import "PreferenceManager.h" + +enum +{ + kLabelTagFilename = 1000, + kLabelTagProgress, + kLabelTagSource, + kLabelTagDestination, + kLabelTagTimeRemaining, + kLabelTagStatus, // 1005 + kLabelTagTimeRemainingLabel +}; + + +// Notification sent when user holds option key and expands/contracts a progress view +static NSString *ProgressViewsShouldResize = @"ProgressViewsShouldResize"; + +@interface ProgressViewController(ProgressViewControllerPrivate) + +- (void)viewDidLoad; +- (void)refreshDownloadInfo; +- (void)moveProgressBarToCurrentView; +- (void)updateButtons; + +@end + +@implementation ProgressViewController + ++ (NSString *)formatTime:(int)seconds +{ + NSMutableString *theTime = [NSMutableString stringWithCapacity:8]; + + NSString *padZero = [NSString stringWithString:@"0"]; + //write out new elapsed time + if (seconds >= 3600) + { + [theTime appendFormat:@"%d:",(seconds / 3600)]; + seconds = seconds % 3600; + } + + NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)]; + if ([elapsedMin length] == 2) + [theTime appendString:[padZero stringByAppendingString:elapsedMin]]; + else + [theTime appendString:elapsedMin]; + + seconds = seconds % 60; + NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds]; + + if ([elapsedSec length] == 2) + [theTime appendString:elapsedSec]; + else + [theTime appendString:[padZero stringByAppendingString:elapsedSec]]; + + return theTime; +} + +// fuzzy time gives back strings like "about 5 seconds" ++ (NSString *)formatFuzzyTime:(int)seconds +{ + // check for seconds first + if (seconds < 60) { + if (seconds < 7) + return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 5]; + if (seconds < 13) + return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 10]; + return [NSString stringWithFormat:NSLocalizedString(@"UnderMin", @"Under a minute")]; + } + // seconds becomes minutes and we keep checking. + seconds = seconds/60; + if (seconds < 60) { + if (seconds < 2) + return [NSString stringWithFormat:NSLocalizedString(@"AboutMin",@"About a minute")]; + // OK, tell the good people how much time we have left. + return [NSString stringWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"), seconds]; + } + //this download will never seemingly never end. now seconds become hours. + seconds = seconds/60; + if (seconds < 2) + return [NSString stringWithFormat:NSLocalizedString(@"AboutHour", @"Over an hour")]; + return [NSString stringWithFormat:NSLocalizedString(@"AboutHours", @"Over %d hours"), seconds]; +} + ++ (NSString *)formatBytes:(float)bytes +{ + // if bytes are negative, we return question marks. + if (bytes < 0) + return [NSString stringWithString:@"?"]; + // bytes first. + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f bytes",bytes]; + // kb + bytes = bytes/1024; + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f KB",bytes]; + // mb + bytes = bytes/1024; + if (bytes < 1024) + return [NSString stringWithFormat:@"%.1f MB",bytes]; + // gb + bytes = bytes/1024; + return [NSString stringWithFormat:@"%.1f GB",bytes]; +} + +#pragma mark - + +- (id)init +{ + if ((self = [super init])) + { + [NSBundle loadNibNamed:@"ProgressView" owner:self]; + + [self viewDidLoad]; + + // Register for notifications when one of the progress views is expanded/contracted + // whilst holding the option button + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(changeCollapsedStateNotification:) + name:ProgressViewsShouldResize + object:nil]; + + [mExpandedRevealButton setEnabled:NO]; + [mExpandedOpenButton setEnabled:NO]; + } + + return self; +} + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self + name:ProgressViewsShouldResize + object:nil]; + + // if we get here because we're quitting, the listener will still be alive + // yet we're going away. As a result, we need to tell the d/l listener to + // forget it ever met us and necko will clean it up on its own. + if (mDownloader) + mDownloader->DetachDownloadDisplay(); + NS_IF_RELEASE(mDownloader); + + [mStartTime release]; + [mSourceURL release]; + [mDestPath release]; + [mProgressBar release]; + + [super dealloc]; +} + +// Save the expand/contract view pref (called when the user clicks the dislosure triangle) +- (void)setCompactViewPref +{ + [[PreferenceManager sharedInstance] setPref:"browser.download.compactView" toBoolean:mViewIsCompact]; +} + +- (void)viewDidLoad +{ + mViewIsCompact = [[PreferenceManager sharedInstance] getBooleanPref:"browser.download.compactView" withSuccess:NULL]; + [mProgressBar retain]; // make sure it survives being moved between views + + if (mViewIsCompact) + [self moveProgressBarToCurrentView]; + + // this isn't necessarily better. Need to profile. + [mProgressBar setUsesThreadedAnimation:YES]; +} + +- (NSView *)view +{ + if (mViewIsCompact) + return (mDownloadDone ? mCompletedViewCompact : mProgressViewCompact); + else + return (mDownloadDone ? mCompletedView : mProgressView); +} + +- (IBAction)toggleDisclosure:(id)sender +{ + mViewIsCompact = !mViewIsCompact; + + [self moveProgressBarToCurrentView]; + + // Is option/alt held down? + if ([[[sender window] currentEvent] modifierFlags] & NSAlternateKeyMask) + { + // Get all progress views to look the same as self + [[NSNotificationCenter defaultCenter] postNotificationName:ProgressViewsShouldResize + object:[NSNumber numberWithBool:mViewIsCompact]]; + } + + // Set the pref only when the user clicks the disclosure triangle + [self setCompactViewPref]; + + // Re-calculate the new view & window sizes + [[NSNotificationCenter defaultCenter] postNotificationName:StackViewReloadNotificationName + object:self]; + [self refreshDownloadInfo]; +} + +- (void)changeCollapsedStateNotification:(NSNotification *)notification +{ + // note that this will get called on the view that is being clicked, as well + // as the other views. Don't do redundant work here, like redrawing. + mViewIsCompact = [[notification object] boolValue]; + // Don't call [enclosingStackView reloadSubviews]; here, because it will be done + // by the original view that was option-clicked, not us +} + +-(void)cancel +{ + mUserCancelled = YES; + + if (mDownloader) // we should always have one + mDownloader->CancelDownload(); + + // clean up downloaded file. - do it here or in CancelDownload? + NSFileManager *fileManager = [NSFileManager defaultManager]; + if ([fileManager isDeletableFileAtPath:mDestPath]) + { + // if we delete it, fantastic. if not, oh well. better to move to trash instead? + [fileManager removeFileAtPath:mDestPath handler:nil]; + } +} + +- (IBAction)close:(id)sender +{ + if (!mDownloadDone) + { + mRemoveWhenDone = YES; + [self cancel]; + } + else + { + [mProgressWindowController removeDownload:self]; + } +} + +- (IBAction)stop:(id)sender +{ + [self cancel]; +} + +- (IBAction)reveal:(id)sender +{ + if ([[NSWorkspace sharedWorkspace] selectFile:mDestPath + inFileViewerRootedAtPath:[mDestPath stringByDeletingLastPathComponent]]) + return; + // hmmm. it didn't work. that's odd. need localized error messages. for now, just beep. + NSBeep(); +} + +- (IBAction)open:(id)sender +{ + if ([[NSWorkspace sharedWorkspace] openFile:mDestPath]) + return; + // hmmm. it didn't work. that's odd. need localized error message. for now, just beep. + NSBeep(); +} + +// Called just before the view will be shown to the user +- (void)downloadDidStart +{ + mStartTime = [[NSDate alloc] init]; +// [mProgressBar startAnimation:self]; // moved to onStartDownload + [self refreshDownloadInfo]; +} + +- (void)downloadDidEnd +{ + mDownloadDone = YES; + mDownloadTime = -[mStartTime timeIntervalSinceNow]; + [mProgressBar stopAnimation:self]; + + [mExpandedCancelButton setEnabled:NO]; + [self refreshDownloadInfo]; +} + +// this handles lots of things. +- (void)refreshDownloadInfo +{ + NSView* curView = [self view]; + + NSString* filename = [mSourceURL lastPathComponent]; + NSString *destPath = [mDestPath stringByAbbreviatingWithTildeInPath]; + NSString* tooltipFormat = NSLocalizedString(mDownloadDone ? @"DownloadedTooltipFormat" : @"DownloadingTooltipFormat", @""); + + id filenameLabel = [curView viewWithTag:kLabelTagFilename]; + [filenameLabel setStringValue:filename]; + [filenameLabel setToolTip:[NSString stringWithFormat:tooltipFormat, [mSourceURL lastPathComponent], mSourceURL, destPath]]; + + id destLabel = [curView viewWithTag:kLabelTagDestination]; + [destLabel setStringValue:destPath]; + + id locationLabel = [curView viewWithTag:kLabelTagSource]; + [locationLabel setStringValue:mSourceURL]; + + if (mDownloadDone) + { + id statusLabel = [curView viewWithTag:kLabelTagStatus]; + if (statusLabel) + { + NSString* statusString; + if (mUserCancelled) + statusString = NSLocalizedString(@"DownloadCancelled", @"Cancelled"); + else if (mDownloadingError) + statusString = NSLocalizedString(@"DownloadInterrupted", @"Interrupted"); + else + statusString = NSLocalizedString(@"DownloadCompleted", @"Completed"); + + [statusLabel setStringValue: statusString]; + } + + // set progress label + id progressLabel = [curView viewWithTag:kLabelTagProgress]; + if (progressLabel) + { + float byteSec = mCurrentProgress / mDownloadTime; + // show how much we downloaded, become some types of disconnects make us think + // we finished successfully + [progressLabel setStringValue:[NSString stringWithFormat: + NSLocalizedString(@"DownloadDoneStatusString", @"%@ of %@ done (at %@/sec)"), + [[self class] formatBytes:mCurrentProgress], + [[self class] formatBytes:mDownloadSize], + [[self class] formatBytes:byteSec]]]; + } + + id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining]; + if (timeLabel) + [timeLabel setStringValue:[[self class] formatTime:(int)mDownloadTime]]; + + id timeLabelLabel = [curView viewWithTag:kLabelTagTimeRemainingLabel]; + if (timeLabelLabel) + [timeLabelLabel setStringValue:NSLocalizedString(@"DownloadRemainingLabelDone", @"Time elapsed:")]; + + [self updateButtons]; + } + else + { + NSTimeInterval elapsedTime = -[mStartTime timeIntervalSinceNow]; + + // update status field + id progressLabel = [curView viewWithTag:kLabelTagProgress]; + if (progressLabel) + { + NSString *statusLabelString = NSLocalizedString(@"DownloadStatusString", @"%@ of %@ total (at %@/sec)"); + float byteSec = mCurrentProgress / elapsedTime; + [progressLabel setStringValue:[NSString stringWithFormat:statusLabelString, + [[self class] formatBytes:mCurrentProgress], + (mDownloadSize > 0 ? [[self class] formatBytes:mDownloadSize] : @"?"), + [[self class] formatBytes:byteSec]]]; + } + + id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining]; + if (timeLabel) + { + if (mDownloadSize > 0) + { + int secToGo = (int)ceil((elapsedTime * mDownloadSize / mCurrentProgress) - elapsedTime); + [timeLabel setStringValue:[[self class] formatFuzzyTime:secToGo]]; + } + else // mDownloadSize is undetermined. Set remaining time to question marks. + { + NSString *calculatingString = NSLocalizedString(@"DownloadCalculatingString", @"Unknown"); + [timeLabel setStringValue:calculatingString]; + } + } + } +} + +- (void)updateButtons +{ + // note: this will stat every time, which will be expensive! We could use + // FNNotify/FNSubscribe to avoid this (writing a Cocoa wrapper around it). + if (mDownloadDone && !mDownloadingError) + { + BOOL destFileExists = [[NSFileManager defaultManager] fileExistsAtPath:mDestPath]; + [mExpandedRevealButton setEnabled:destFileExists]; + [mExpandedOpenButton setEnabled:destFileExists]; + } +} + +- (void)moveProgressBarToCurrentView +{ + [mProgressBar moveToView:(mViewIsCompact ? mProgressViewCompact : mProgressView) resize:YES]; + [mProgressBar startAnimation:self]; // this is necessary to keep it animating for some reason +} + +- (void)setProgressWindowController:(ProgressDlgController*)progressWindowController +{ + mProgressWindowController = progressWindowController; +} + +- (BOOL)isActive +{ + return !mDownloadDone; +} + +#pragma mark - + +- (void)onStartDownload:(BOOL)isFileSave +{ + mIsFileSave = isFileSave; + [self downloadDidStart]; + [mProgressWindowController didStartDownload:self]; + + // need to do this after the view as been put in the window, otherwise it doesn't work + [mProgressBar startAnimation:self]; +} + +- (void)onEndDownload:(BOOL)completedOK +{ + mDownloadingError = !completedOK; + + [self downloadDidEnd]; + [mProgressWindowController didEndDownload:self]; + if (mRemoveWhenDone) + [mProgressWindowController removeDownload:self]; +} + +- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress +{ + mCurrentProgress = aCurProgress; // fall back for stat calcs + mDownloadSize = aMaxProgress; + + if (![mProgressBar isIndeterminate]) //most likely - just update value + { + if (aCurProgress == aMaxProgress) //handles little bug in FTP download size + [mProgressBar setMaxValue:aMaxProgress]; + + [mProgressBar setDoubleValue:aCurProgress]; + } + else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values + { + [mProgressBar setIndeterminate:NO]; + [mProgressBar setMaxValue:aMaxProgress]; + [mProgressBar setDoubleValue:aCurProgress]; + } // if neither case was true, it's barber pole city. +} + +-(void)setDownloadListener:(CHDownloader*)aDownloader +{ + if (mDownloader != aDownloader) + NS_IF_RELEASE(mDownloader); + + NS_IF_ADDREF(mDownloader = aDownloader); +} + +#if 0 +/* + This is kind of a hack. It should probably be done somewhere else so Mozilla can have + it too, but until Apple fixes the problems with the setting of comments without + reverting to Applescript, I have left it in. + + Turned off for now, until we find a better way to do this. Won't Carbon APIs work? +*/ +- (void)tryToSetFinderComments +{ + if (mDestPath && mSourceURL) + { + CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL, + (CFStringRef)mDestPath, + kCFURLPOSIXPathStyle, + NO); + + NSString *hfsPath = (NSString *)CFURLCopyFileSystemPath(fileURL, + kCFURLHFSPathStyle); + + CFRelease(fileURL); + + NSAppleScript *setCommentScript = [[NSAppleScript alloc] initWithSource: + [NSString stringWithFormat:@"tell application \"Finder\" to set comment of file \"%@\" to \"%@\"", hfsPath, mSourceURL]]; + NSDictionary *errorInfo = NULL; + + [setCommentScript executeAndReturnError:&errorInfo]; + + if (errorInfo) + { + NSLog(@"Get error when running AppleScript to set comments for '%@':\n %@", + mDestPath, + [errorInfo objectForKey:NSAppleScriptErrorMessage]); + } + } +} +#endif + +- (void)setSourceURL:(NSString*)aSourceURL +{ + [mSourceURL autorelease]; + mSourceURL = [aSourceURL copy]; + + //[self tryToSetFinderComments]; +} + +- (void)setDestinationPath:(NSString*)aDestPath +{ + [mDestPath autorelease]; + mDestPath = [aDestPath copy]; + //[self tryToSetFinderComments]; +} + +@end diff --git a/chimera/src/download/SaveHeaderSniffer.h b/chimera/src/download/SaveHeaderSniffer.h index 4147cce1507..e69de29bb2d 100644 --- a/chimera/src/download/SaveHeaderSniffer.h +++ b/chimera/src/download/SaveHeaderSniffer.h @@ -1,84 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Chimera code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * David Hyatt - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -#import -#import - -#include "nsString.h" -#include "nsIWebProgressListener.h" -#include "nsIWebBrowserPersist.h" -#include "nsIURI.h" -#include "nsILocalFile.h" -#include "nsIInputStream.h" -#include "nsIDOMDocument.h" - - -// Implementation of a header sniffer class that is used when saving Web pages and images. -class nsHeaderSniffer : public nsIWebProgressListener -{ -public: - nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL, - nsIDOMDocument* aDocument, nsIInputStream* aPostData, - const nsAString& aSuggestedFilename, PRBool aBypassCache, - NSView* aFilterView, NSPopUpButton* aFilterList); - virtual ~nsHeaderSniffer(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIWEBPROGRESSLISTENER - -protected: - - nsresult PerformSave(nsIURI* inOriginalURI); - nsresult InitiateDownload(nsISupports* inSourceData, nsString& inFileName, nsIURI* inOriginalURI); - -private: - - nsIWebBrowserPersist* mPersist; // Weak. It owns us as a listener. - nsCOMPtr mTmpFile; - nsCOMPtr mURL; - nsCOMPtr mDocument; - nsCOMPtr mPostData; - nsString mDefaultFilename; - PRBool mBypassCache; - nsCString mContentType; - nsCString mContentDisposition; - NSView* mFilterView; - NSPopUpButton* mFilterList; -}; - diff --git a/chimera/src/download/SaveHeaderSniffer.mm b/chimera/src/download/SaveHeaderSniffer.mm index 42827fa633c..77ccd5842d7 100644 --- a/chimera/src/download/SaveHeaderSniffer.mm +++ b/chimera/src/download/SaveHeaderSniffer.mm @@ -38,6 +38,8 @@ #import "NSString+Utils.h" +#import "ChimeraUIConstants.h" + #include "SaveHeaderSniffer.h" #include "netCore.h" @@ -56,7 +58,7 @@ const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrows nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData, const nsAString& aSuggestedFilename, PRBool aBypassCache, - NSView* aFilterView, NSPopUpButton* aFilterList) + NSView* aFilterView) : mPersist(aPersist) , mTmpFile(aFile) , mURL(aURL) @@ -65,9 +67,8 @@ nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, , mDefaultFilename(aSuggestedFilename) , mBypassCache(aBypassCache) , mFilterView(aFilterView) -, mFilterList(aFilterList) { - NS_INIT_ISUPPORTS(); + NS_INIT_ISUPPORTS(); } nsHeaderSniffer::~nsHeaderSniffer() @@ -183,14 +184,16 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) return rv; nsCOMPtr dirBranch; prefs->GetBranch("browser.download.", getter_AddRefs(dirBranch)); - PRInt32 filterIndex = 0; + PRInt32 filterIndex = eSaveFormatHTMLComplete; if (dirBranch) { nsresult rv = dirBranch->GetIntPref("save_converter_index", &filterIndex); if (NS_FAILED(rv)) - filterIndex = 0; + filterIndex = eSaveFormatHTMLComplete; } - if (mFilterList) - [mFilterList selectItemAtIndex: filterIndex]; + + NSPopUpButton* filterList = [mFilterView viewWithTag:kSaveFormatPopupTag]; + if (filterList) + [filterList selectItemAtIndex: filterIndex]; // We need to figure out what file name to use. nsAutoString defaultFileName; @@ -294,17 +297,17 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI) return NS_OK; // Update the filter index. - if (isHTML && mFilterList) { - filterIndex = [mFilterList indexOfSelectedItem]; + if (isHTML && filterList) { + filterIndex = [filterList indexOfSelectedItem]; dirBranch->SetIntPref("save_converter_index", filterIndex); } // Convert the content type to text/plain if it was selected in the filter. - if (isHTML && filterIndex == 2) + if (isHTML && filterIndex == eSaveFormatPlainText) mContentType = "text/plain"; nsCOMPtr sourceData; - if (isHTML && filterIndex != 1) + if (isHTML && filterIndex != eSaveFormatHTMLSource) sourceData = do_QueryInterface(mDocument); else sourceData = do_QueryInterface(mURL); diff --git a/chimera/src/download/nsDownloadListener.h b/chimera/src/download/nsDownloadListener.h index c76874c71d9..e69de29bb2d 100644 --- a/chimera/src/download/nsDownloadListener.h +++ b/chimera/src/download/nsDownloadListener.h @@ -1,93 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - - -#import -#import - -#import "CHDownloadProgressDisplay.h" - -#include "nsString.h" -#include "nsIDownload.h" -#include "nsIWebProgressListener.h" -#include "nsIWebBrowserPersist.h" -#include "nsIURI.h" -#include "nsILocalFile.h" -#include "nsExternalHelperAppService.h" - - -// maybe this should replace nsHeaderSniffer too? - -class nsDownloadListener : public CHDownloader, - public nsIDownload, - public nsIWebProgressListener -{ -public: - nsDownloadListener(DownloadControllerFactory* inDownloadControllerFactory); - virtual ~nsDownloadListener(); - - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIDOWNLOAD - NS_DECL_NSIWEBPROGRESSLISTENER - -public: - //void BeginDownload(); - void InitDialog(); - - virtual void PauseDownload(); - virtual void ResumeDownload(); - virtual void CancelDownload(); - virtual void DownloadDone(); - virtual void DetachDownloadDisplay(); - -private: - - // These two are mutually exclusive - nsCOMPtr mWebPersist; // Our web persist object. - nsCOMPtr mHelperAppLauncher; // If we're talking to uriloader - - nsCOMPtr mURI; // The URI of our source file. Null if we're saving a complete document. - nsCOMPtr mDestination; // Our destination URL. - PRInt64 mStartTime; // When the download started - PRPackedBool mBypassCache; // Whether we should bypass the cache or not. - PRPackedBool mNetworkTransfer; // true if the first OnStateChange has the NETWORK bit set - PRPackedBool mGotFirstStateChange; // true after we've seen the first OnStateChange - PRPackedBool mUserCanceled; // true if the user canceled the download -}; - diff --git a/chimera/src/download/nsDownloadListener.mm b/chimera/src/download/nsDownloadListener.mm index 8acb6b28c53..0fb52f20c6a 100644 --- a/chimera/src/download/nsDownloadListener.mm +++ b/chimera/src/download/nsDownloadListener.mm @@ -21,7 +21,7 @@ * * Contributor(s): * Simon Fraser - * + * Calum Robinson * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -46,20 +46,25 @@ #include "nsIURL.h" #include "netCore.h" -nsDownloadListener::nsDownloadListener(DownloadControllerFactory* inControllerFactory) -: CHDownloader(inControllerFactory) +nsDownloadListener::nsDownloadListener() +: mDownloadStatus(NS_OK) , mBypassCache(PR_FALSE) , mNetworkTransfer(PR_FALSE) , mGotFirstStateChange(PR_FALSE) , mUserCanceled(PR_FALSE) +, mSentCancel(PR_FALSE) { + mStartTime = LL_ZERO; } nsDownloadListener::~nsDownloadListener() { + // if we go away before the timer fires, cancel it + if (mEndRefreshTimer) + mEndRefreshTimer->Cancel(); } -NS_IMPL_ISUPPORTS_INHERITED2(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener) +NS_IMPL_ISUPPORTS_INHERITED3(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener, nsITimerCallback) #pragma mark - @@ -193,14 +198,14 @@ nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { - if (mUserCanceled) + if (mUserCanceled && !mSentCancel) { if (mHelperAppLauncher) mHelperAppLauncher->Cancel(); else if (aRequest) aRequest->Cancel(NS_BINDING_ABORTED); - mUserCanceled = false; + mSentCancel = PR_TRUE; } [mDownloadDisplay setProgressTo:aCurTotalProgress ofMax:aMaxTotalProgress]; @@ -236,7 +241,7 @@ nsDownloadListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *a // Implementation of nsIWebProgressListener /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in unsigned long aStatus); */ NS_IMETHODIMP -nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, +nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, PRUint32 aStatus) { // NSLog(@"State changed: state %u, status %u", aStateFlags, aStatus); @@ -250,29 +255,64 @@ nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRe // the window and controller. We will get this even in the event of a cancel, // so this is the only place in the listener where we should kill the download. if ((aStateFlags & STATE_STOP) && (!mNetworkTransfer || (aStateFlags & STATE_IS_NETWORK))) { - DownloadDone(); + DownloadDone(aStatus); } return NS_OK; } #pragma mark - +// nsITimerCallback implementation +NS_IMETHODIMP nsDownloadListener::Notify(nsITimer *timer) +{ + // resset the destination, since uniquifying the filename may have + // changed it + nsAutoString pathStr; + mDestination->GetPath(pathStr); + [mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]]; + + // cancelling should give us a failure status + [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(mDownloadStatus) && !mUserCanceled)]; + mEndRefreshTimer = NULL; + return NS_OK; +} + +#pragma mark - + void nsDownloadListener::InitDialog() { // dialog has to be shown before the outlets get hooked up - [mDownloadDisplay onStartDownload:(BOOL)IsFileSave()]; - if (mURI) { nsCAutoString spec; - mURI->GetSpec(spec); + + // we need to be careful not to show a password in the url + nsCAutoString userPassword; + mURI->GetUserPass(userPassword); + if (!userPassword.IsEmpty()) + { + // ugh, build it by hand + nsCAutoString hostport, path; + mURI->GetScheme(spec); + mURI->GetHostPort(hostport); + mURI->GetPath(path); + + spec.Append("://"); + spec.Append(hostport); + spec.Append(path); + } + else + mURI->GetSpec(spec); + [mDownloadDisplay setSourceURL: [NSString stringWithUTF8String:spec.get()]]; } nsAutoString pathStr; mDestination->GetPath(pathStr); [mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]]; + + [mDownloadDisplay onStartDownload:IsFileSave()]; } void @@ -292,19 +332,19 @@ nsDownloadListener::CancelDownload() { mUserCanceled = PR_TRUE; - if (mWebPersist) + if (mWebPersist && !mSentCancel) { mWebPersist->CancelSave(); - mUserCanceled = PR_FALSE; + mSentCancel = PR_TRUE; } // delete any files we've created... - + // DownloadDone will get called (eventually) } void -nsDownloadListener::DownloadDone() +nsDownloadListener::DownloadDone(nsresult aStatus) { // break the reference cycle by removing ourselves as a listener if (mWebPersist) @@ -314,8 +354,23 @@ nsDownloadListener::DownloadDone() } mHelperAppLauncher = nsnull; - - [mDownloadDisplay onEndDownload]; + mDownloadStatus = aStatus; + + // hack alert! + // Our destination file gets uniquified after the OnStop notification is sent + // (in nsExternalAppHandler::ExecuteDesiredAction), so we never get a chance + // to figure out the final filename. To work around this, set a timer to fire + // in the near future, from which we'll send the done callback. + mEndRefreshTimer = do_CreateInstance("@mozilla.org/timer;1"); + if (mEndRefreshTimer) + { + nsresult rv = mEndRefreshTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT); // defaults to 1-shot, normal priority + if (NS_FAILED(rv)) + mEndRefreshTimer = NULL; + } + + if (!mEndRefreshTimer) // timer creation or init failed, so just do it now + [mDownloadDisplay onEndDownload:(NS_SUCCEEDED(aStatus) && !mUserCanceled)]; } // diff --git a/chimera/src/embedding/CHBrowserService.mm b/chimera/src/embedding/CHBrowserService.mm index 0026795c567..6c0133b34e2 100644 --- a/chimera/src/embedding/CHBrowserService.mm +++ b/chimera/src/embedding/CHBrowserService.mm @@ -38,7 +38,6 @@ #import "NSString+Utils.h" #import "CHBrowserService.h" -#import "CHDownloadFactories.h" #import "CHBrowserView.h" #include "nsIWindowWatcher.h" @@ -107,14 +106,6 @@ CHBrowserService::InitEmbedding() static NS_DEFINE_CID(kHelperDlgCID, NS_HELPERAPPLAUNCHERDIALOG_CID); nsresult rv = cr->RegisterFactory(kHelperDlgCID, NS_IHELPERAPPLAUNCHERDLG_CLASSNAME, NS_IHELPERAPPLAUNCHERDLG_CONTRACTID, sSingleton); - - // replace the downloader with our own which does not rely on the xpfe downlaod manager - nsCOMPtr downloadFactory; - rv = NewDownloadListenerFactory(getter_AddRefs(downloadFactory)); - if (NS_FAILED(rv)) return rv; - - static NS_DEFINE_CID(kDownloadCID, NS_DOWNLOAD_CID); - rv = cr->RegisterFactory(kDownloadCID, "Download", NS_DOWNLOAD_CONTRACTID, downloadFactory); return rv; } diff --git a/chimera/src/embedding/CHBrowserView.h b/chimera/src/embedding/CHBrowserView.h index c7f87ee2b90..ff000640c7e 100644 --- a/chimera/src/embedding/CHBrowserView.h +++ b/chimera/src/embedding/CHBrowserView.h @@ -163,9 +163,8 @@ enum { // nsIWebBrowserSetup methods - (void)setProperty:(unsigned int)property toValue:(unsigned int)value; -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList; -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView; +- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename; - (void)printDocument; - (void)pageSetup; diff --git a/chimera/src/embedding/CHBrowserView.mm b/chimera/src/embedding/CHBrowserView.mm index 43feb519bee..4179f8260eb 100644 --- a/chimera/src/embedding/CHBrowserView.mm +++ b/chimera/src/embedding/CHBrowserView.mm @@ -430,7 +430,6 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; suggestedFilename: (NSString*)aFileName bypassCache: (BOOL)aBypassCache filterView: (NSView*)aFilterView - filterList: (NSPopUpButton*)aFilterList { // Create our web browser persist object. This is the object that knows // how to actually perform the saving of the page (and of the images @@ -477,7 +476,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; [aFileName assignTo_nsAString:fileName]; nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI, aDocument, postData, fileName, aBypassCache, - aFilterView, aFilterList); + aFilterView); if (!sniffer) return; webPersist->SetProgressListener(sniffer); // owned @@ -572,8 +571,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; return found; } -- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList - url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename +- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename { nsCOMPtr url; nsresult rv = NS_NewURI(getter_AddRefs(url), [aURLSpec UTF8String]); @@ -584,8 +582,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; withDocument: nsnull suggestedFilename: aFilename bypassCache: YES - filterView: aFilterView - filterList: aFilterList]; + filterView: aFilterView]; } -(NSString*)getFocusedURLString @@ -616,7 +613,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; return [NSString stringWith_nsAString: urlStr]; } -- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList +- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView { if (!_webBrowser) return; @@ -656,8 +653,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1"; withDocument: domDocument suggestedFilename: @"" bypassCache: NO - filterView: aFilterView - filterList: aFilterList]; + filterView: aFilterView]; } -(void)doCommand:(const char*)commandName diff --git a/chimera/src/embedding/CHDownloadProgressDisplay.h b/chimera/src/embedding/CHDownloadProgressDisplay.h index 03b8e659354..e69de29bb2d 100644 --- a/chimera/src/embedding/CHDownloadProgressDisplay.h +++ b/chimera/src/embedding/CHDownloadProgressDisplay.h @@ -1,167 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Chimera code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* - The classes and protocol in this file allow Cocoa applications to easily - reuse the underlying download implementation, which deals with the complexity - of Gecko's downloading callbacks. - - There are three things here: - - 1. The CHDownloadProgressDisplay protocol. - - This is a formal protocol that needs to be implemented by - a window controller for your progress window. Its methods - will be called by the underlying C++ downloading classes. - - 2. The Obj-C DownloadControllerFactory class. - - This class should be subclassed by an embedder, with an - implementation of 'createDownloadController' that hands back - a new instance of an NSWindowController that implements the - protocol. - - The underlying C++ classes use this factory to create the - progress window controller. - - 3. The CHDownloader C++ class - - This base class exists to hide the complextity of the download - listener classes (which deal with Gecko callbacks) from the - window controller. Embedders don't need to do anything with it. - - How these classes fit together: - - There are 2 ways in which a download is initiated: - - (i) File->Save. - - Chimera does a complex dance here in order to get certain - information about the data being downloaded (it needs to - start the download before it can read some optional MIME headers). - - CBrowserView creates an nsIWebBrowserPersist (WBP), and then a - nsHeaderSniffer, which implements nsIWebProgressListener and is set to - observer the WBP. When nsHeaderSniffer hears about the start of the - download, it decides on a file name, and what format to save the data - in. It then cancels the current WPB, makes another one, and does - a CreateInstance of an nsIDownload (making one of our nsDownloadListener - -- aka nsDownloder -- objects), and sets that as the nsIWebProgressListener. - The full download procedes from there. - - (ii) Click to download (e.g. FTP link) - - This is simpler. The backend (necko) does the CreateInstance of the - nsIDownload, and the download progresses. - - In both cases, creating the nsDownloadListener and calling its Init() method - calls nsDownloder::CreateDownloadDisplay(). The nsDownloder has as a member - variable a DownloadControllerFactory (see above), which got passed to it - via our XPCOM factory for nsIDownload objects. It then uses that DownloadControllerFactory - to get an instance of the download progress window controller, which then - shows the download progress window. - - Simple, eh? - -*/ - -#import - -#include "nsISupports.h" - -class CHDownloader; - -// a formal protocol for something that implements progress display -// Embedders can make a window controller that conforms to this -// protocol, and reuse nsDownloadListener to get download UI. -@protocol CHDownloadProgressDisplay - -- (void)onStartDownload:(BOOL)isFileSave; -- (void)onEndDownload; - -- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress; - -- (void)setDownloadListener:(CHDownloader*)aDownloader; -- (void)setSourceURL:(NSString*)aSourceURL; -- (void)setDestinationPath:(NSString*)aDestPath; - -@end - -// subclass this, and have your subclass instantiate and return your window -// controller in createDownloadController -@interface DownloadControllerFactory : NSObject -{ -} - -- (NSWindowController *)createDownloadController; - -@end - - -// Pure virtual base class for a generic downloader, that the progress UI can talk to. -// It implements nsISupports so that it can be refcounted. This class insulates the -// UI code from having to know too much about the nsIDownloadListener. -// It is responsible for creating the download UI, via the DownloadControllerFactory -// that it owns. -class CHDownloader : public nsISupports -{ -public: - CHDownloader(DownloadControllerFactory* inControllerFactory); - virtual ~CHDownloader(); - - NS_DECL_ISUPPORTS - - virtual void PauseDownload() = 0; - virtual void ResumeDownload() = 0; - virtual void CancelDownload() = 0; - virtual void DownloadDone() = 0; - virtual void DetachDownloadDisplay() = 0; // tell downloader to forget about its display - - virtual void CreateDownloadDisplay(); - -protected: - - PRBool IsFileSave() { return mIsFileSave; } - void SetIsFileSave(PRBool inIsFileSave) { mIsFileSave = inIsFileSave; } - -protected: - - DownloadControllerFactory* mControllerFactory; - id mDownloadDisplay; // something that implements the CHDownloadProgressDisplay protocol - PRBool mIsFileSave; // true if we're doing a save, rather than a download -}; - diff --git a/chimera/src/embedding/CHDownloadProgressDisplay.mm b/chimera/src/embedding/CHDownloadProgressDisplay.mm index 3f384b9fa90..e69de29bb2d 100644 --- a/chimera/src/embedding/CHDownloadProgressDisplay.mm +++ b/chimera/src/embedding/CHDownloadProgressDisplay.mm @@ -1,76 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Chimera code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import "CHDownloadProgressDisplay.h" - - -@implementation DownloadControllerFactory - -- (NSWindowController *)createDownloadController -{ - // a dummy implementation. You should provide a subclass that - // returns an instance of your progress dialog controller. - return nil; -} - -@end - -#pragma mark - - -// see the header file for comments -CHDownloader::CHDownloader(DownloadControllerFactory* inControllerFactory) -: mControllerFactory(inControllerFactory) -, mDownloadDisplay(nil) -, mIsFileSave(PR_FALSE) -{ - NS_INIT_ISUPPORTS(); - [mControllerFactory retain]; -} - -CHDownloader::~CHDownloader() -{ - [mControllerFactory release]; -} - -NS_IMPL_ISUPPORTS1(CHDownloader, nsISupports); - -void -CHDownloader::CreateDownloadDisplay() -{ - mDownloadDisplay = [mControllerFactory createDownloadController]; - [mDownloadDisplay setDownloadListener:this]; -} diff --git a/chimera/src/extensions/CHStackView.h b/chimera/src/extensions/CHStackView.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/src/extensions/CHStackView.m b/chimera/src/extensions/CHStackView.m new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/src/extensions/NSView+Utils.h b/chimera/src/extensions/NSView+Utils.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/src/extensions/NSView+Utils.m b/chimera/src/extensions/NSView+Utils.m new file mode 100644 index 00000000000..e69de29bb2d diff --git a/chimera/src/extensions/RDFOutlineViewDataSource.h b/chimera/src/extensions/RDFOutlineViewDataSource.h index f75ab400132..81c6ce491ce 100644 --- a/chimera/src/extensions/RDFOutlineViewDataSource.h +++ b/chimera/src/extensions/RDFOutlineViewDataSource.h @@ -51,24 +51,31 @@ class nsIRDFService; @interface RDFOutlineViewItem : NSObject { nsIRDFResource* mResource; + unsigned int mCacheVersion; // if matches the cache version in the data source, + // cached values are valid + BOOL mExpandable; + int mNumChildren; + NSArray* mChildNodes; } -- (nsIRDFResource*) resource; -- (void) setResource: (nsIRDFResource*) aResource; +- (nsIRDFResource*)resource; // addRefs the result +- (void)setResource:(nsIRDFResource*) aResource; @end -@interface RDFOutlineViewDataSource : NSObject { - nsIRDFDataSource* mDataSource; - nsIRDFContainer* mContainer; - nsIRDFContainerUtils* mContainerUtils; - nsIRDFResource* mRootResource; - nsIRDFService* mRDFService; +@interface RDFOutlineViewDataSource : NSObject +{ + nsIRDFDataSource* mDataSource; + nsIRDFContainer* mContainer; + nsIRDFContainerUtils* mContainerUtils; + nsIRDFResource* mRootResource; + nsIRDFService* mRDFService; - IBOutlet ExtendedOutlineView* mOutlineView; + IBOutlet ExtendedOutlineView* mOutlineView; - NSMutableDictionary* mDictionary; + NSMutableDictionary* mDictionary; + unsigned int mCacheVersion; } // Initialization Methods @@ -85,7 +92,6 @@ class nsIRDFService; - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item; - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item; - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; -- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; // tooltip support from the ExtendedOutlineView. Override to provide a tooltip // other than the Name property for each item in the view. @@ -94,14 +100,14 @@ class nsIRDFService; - (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren; // Implementation Methods -- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource; +- (id)getWrapperFor:(nsIRDFResource*) aRDFResource; +- (void)invalidateCachedItems; // override to do something different with the cell data rather than just // return a string (add an icon in an attributed string, for example). --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; +- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem; --(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem - result:(PRUnichar**)outResult; +- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem; @end diff --git a/chimera/src/extensions/RDFOutlineViewDataSource.mm b/chimera/src/extensions/RDFOutlineViewDataSource.mm index 9b5993d91d1..a293b6a23b2 100644 --- a/chimera/src/extensions/RDFOutlineViewDataSource.mm +++ b/chimera/src/extensions/RDFOutlineViewDataSource.mm @@ -41,6 +41,7 @@ #import "RDFOutlineViewDataSource.h" #import "CHBrowserService.h" +#include "nsCRT.h" #include "nsIRDFDataSource.h" #include "nsIRDFService.h" #include "nsIRDFLiteral.h" @@ -55,14 +56,116 @@ #include "nsXPIDLString.h" #include "nsString.h" -@interface RDFOutlineViewDataSource(Private); -- (void)registerForShutdownNotification; -- (void)cleanup; +@interface RDFOutlineViewItem(Private) + +- (unsigned int)cacheVersion; +- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version; +- (void)setChildren:(NSArray*)childArray; +- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren; +- (BOOL)cachedChildren; + +- (BOOL)isExpandable; +- (int)numChildren; +- (id)childAtIndex:(int)index; @end +@implementation RDFOutlineViewItem + +- (id)init +{ + if ((self = [super init])) + { + mCacheVersion = 0; + mExpandable = NO; + mNumChildren = 0; + } + return self; +} + +- (void)dealloc +{ + [mChildNodes release]; + NS_IF_RELEASE(mResource); + [super dealloc]; +} + +- (nsIRDFResource*)resource +{ + NS_IF_ADDREF(mResource); + return mResource; +} + +- (void)setResource:(nsIRDFResource*) aResource +{ + nsIRDFResource* oldResource = mResource; + NS_IF_ADDREF(mResource = aResource); + NS_IF_RELEASE(oldResource); +} + +- (unsigned int)cacheVersion +{ + return mCacheVersion; +} + +- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version; +{ + mNumChildren = numChildren; + mExpandable = expandable; + mCacheVersion = version; +} + +- (void)setChildren:(NSArray*)childArray +{ + // childArray can legally be nil here. If it is, we're clearing the cached children + NSArray* oldChildren = mChildNodes; + mChildNodes = childArray; + [mChildNodes retain]; + [oldChildren release]; +} + +- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren; +{ + return (mCacheVersion == version) && (needChildren ? (mChildNodes != nil) : 1); +} + +- (BOOL)cachedChildren +{ + return (mChildNodes != nil); +} + +- (BOOL)isExpandable +{ + return mExpandable; +} + +- (int)numChildren +{ + return mNumChildren; +} + +- (id)childAtIndex:(int)index +{ + if (mChildNodes) + return [mChildNodes objectAtIndex:index]; + + return nil; +} + +@end + +#pragma mark - + +@interface RDFOutlineViewDataSource(Private) + +- (void)registerForShutdownNotification; +- (void)cleanup; +- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren; + +@end + @implementation RDFOutlineViewDataSource - (id)init @@ -70,6 +173,7 @@ if ((self = [super init])) { [self registerForShutdownNotification]; + mCacheVersion = 1; } return self; } @@ -78,7 +182,7 @@ { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [self cleanup]; + [self cleanup]; [super dealloc]; } @@ -167,123 +271,62 @@ // XXX - For now, we'll just say that none of our items are editable, as we aren't using any // RDF datasources that are mutable. // -- (BOOL) outlineView: (NSOutlineView*) aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn +- (BOOL) outlineView: (NSOutlineView*)aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn item: (id) aItem { - return NO; + return NO; } -- (BOOL) outlineView: (NSOutlineView*) aOutlineView isItemExpandable: (id) aItem +- (BOOL) outlineView: (NSOutlineView*)aOutlineView isItemExpandable:(id)aItem { - if (!mDataSource) - return NO; - - if (!aItem) - return YES; // The root is always open - - nsCOMPtr itemResource = dont_AddRef([aItem resource]); - - PRBool isSeq = PR_FALSE; - mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq); - if (isSeq) - return YES; - - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNode; - mDataSource->GetTarget(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNode)); - - return childNode != nsnull; + if (!mDataSource) + return NO; + + if (!aItem) + return YES; // The root is always open + + if (![aItem cacheValid:mCacheVersion needChildren:NO]) + [self updateItemProperties:aItem enumerateChildren:NO]; + + return [aItem isExpandable]; } -- (id) outlineView: (NSOutlineView*) aOutlineView child: (int) aIndex - ofItem: (id) aItem +- (id)outlineView:(NSOutlineView*)aOutlineView child:(int)aIndex ofItem:(id)aItem { - if (!mDataSource) - return nil; + if (!mDataSource) + return nil; + + if (!aItem) + { + nsCOMPtr rootResource = dont_AddRef([self rootResource]); + aItem = [self getWrapperFor:rootResource]; + } + + if (![aItem cacheValid:mCacheVersion needChildren:YES]) + [self updateItemProperties:aItem enumerateChildren:YES]; - nsCOMPtr resource = !aItem ? dont_AddRef([self rootResource]) : dont_AddRef([aItem resource]); - - nsCOMPtr ordinalResource; - mContainerUtils->IndexToOrdinalResource(aIndex + 1, getter_AddRefs(ordinalResource)); - - nsCOMPtr childNode; - mDataSource->GetTarget(resource, ordinalResource, PR_TRUE, getter_AddRefs(childNode)); - if (childNode) { - // Yay. A regular container. We don't need to count, we can go directly to - // our object. - nsCOMPtr childResource(do_QueryInterface(childNode)); - if (childResource) - return [self makeWrapperFor:childResource]; - } - else - { - // Oh well, not a regular container. We need to count, dagnabbit. - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNodes; - mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); - - nsCOMPtr supp; - PRInt32 count = 0; - - PRBool hasMore = PR_FALSE; - while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) - { - childNodes->GetNext(getter_AddRefs(supp)); - if (count == aIndex) - break; - count ++; - } - - nsCOMPtr childResource(do_QueryInterface(supp)); - if (childResource) { - return [self makeWrapperFor:childResource]; - } - } - - return nil; + return [aItem childAtIndex:aIndex]; } -- (int) outlineView: (NSOutlineView*) aOutlineView numberOfChildrenOfItem: (id) aItem; +- (int)outlineView:(NSOutlineView*)aOutlineView numberOfChildrenOfItem:(id) aItem; { - if (!mDataSource) - return 0; - - nsCOMPtr resource = dont_AddRef(aItem ? [aItem resource] : [self rootResource]); - - // XXX just assume NC:child is the only containment arc for now - nsCOMPtr childProperty; - mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); - - nsCOMPtr childNodes; - mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); - - PRBool hasMore = PR_FALSE; - PRInt32 count = 0; - - while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) - { - nsCOMPtr supp; - childNodes->GetNext(getter_AddRefs(supp)); - count ++; - } - - if (count == 0) { - nsresult rv = mContainer->Init(mDataSource, resource); - if (NS_FAILED(rv)) - return 0; - - mContainer->GetCount(&count); - } - - return count; + if (!mDataSource) + return 0; + + if (!aItem) + { + nsCOMPtr rootResource = dont_AddRef([self rootResource]); + aItem = [self getWrapperFor:rootResource]; + } + + if (![aItem cacheValid:mCacheVersion needChildren:YES]) + [self updateItemProperties:aItem enumerateChildren:YES]; + + return [aItem numChildren]; } -- (id) outlineView: (NSOutlineView*) aOutlineView objectValueForTableColumn: (NSTableColumn*) aTableColumn - byItem: (id) aItem +- (id)outlineView:(NSOutlineView*)aOutlineView objectValueForTableColumn:(NSTableColumn*)aTableColumn + byItem:(id)aItem { if (!mDataSource || !aItem) return nil; @@ -291,25 +334,22 @@ // The table column's identifier is the RDF Resource URI of the property being displayed in // that column, e.g. "http://home.netscape.com/NC-rdf#Name" NSString* columnPropertyURI = [aTableColumn identifier]; - nsXPIDLString literalValue; - [self getPropertyString:columnPropertyURI forItem:aItem result:getter_Copies(literalValue)]; + NSString* propString = [self getPropertyString:columnPropertyURI forItem:aItem]; - return [self createCellContents:literalValue withColumn:columnPropertyURI byItem:aItem]; + return [self createCellContents:propString withColumn:columnPropertyURI byItem:aItem]; } - // // createCellContents:withColumn:byItem // // Constructs a NSString from the given string data for this item in the given column. // This should be overridden to do more fancy things, such as add an icon, etc. // --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem +- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem { - return [NSString stringWith_nsAString: inValue]; + return inValue; } - // // outlineView:tooltipForString // @@ -318,21 +358,9 @@ // - (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem { - nsXPIDLString literalValue; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem result:getter_Copies(literalValue)]; - return [NSString stringWith_nsAString:literalValue]; + return [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem]; } - -- (void) outlineView: (NSOutlineView*) aOutlineView setObjectValue: (id) aObject - forTableColumn: (NSTableColumn*) aTableColumn - byItem: (id) aItem -{ - -} - - - - (void) reloadDataForItem: (id) aItem reloadChildren: (BOOL) aReloadChildren { if (!aItem) @@ -341,7 +369,7 @@ [mOutlineView reloadItem: aItem reloadChildren: aReloadChildren]; } -- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource +- (id)getWrapperFor:(nsIRDFResource*) aRDFResource { const char* k; aRDFResource->GetValueConst(&k); @@ -350,8 +378,9 @@ // see if we've created a wrapper already, if not, create a new wrapper object // and stash it in our dictionary RDFOutlineViewItem* item = [mDictionary objectForKey:key]; - if (!item) { - item = [[RDFOutlineViewItem alloc] init]; + if (!item) + { + item = [[[RDFOutlineViewItem alloc] init] autorelease]; [item setResource: aRDFResource]; [mDictionary setObject:item forKey:key]; // retains |item| } @@ -359,14 +388,56 @@ return item; } - --(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem - result:(PRUnichar**)outResult +- (void)invalidateCachedItems { - if ( !outResult ) - return; - *outResult = nil; + mCacheVersion++; +} + +- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren +{ + BOOL isExpandable = NO; + NSMutableArray* itemChildren = doChildren ? [[[NSMutableArray alloc] initWithCapacity:10] autorelease] : nil; + nsCOMPtr itemResource = dont_AddRef([item resource]); + + PRBool isSeq = PR_FALSE; + mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq); + if (isSeq) + isExpandable = YES; + + nsCOMPtr childProperty; + mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty)); + + nsCOMPtr childNodes; + mDataSource->GetTargets(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNodes)); + + PRBool hasMore = PR_FALSE; + while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore) + { + nsCOMPtr supp; + childNodes->GetNext(getter_AddRefs(supp)); + + nsCOMPtr childResource = do_QueryInterface(supp); + if (childResource) + { + id childItem = [self getWrapperFor:childResource]; + if (childItem) + { + isExpandable = YES; + if (!itemChildren) break; // know enough already + [itemChildren addObject:childItem]; + } + } + } + + // itemChildren will be nil here if we don't care about children, but that's OK. + // the setChildren call will clear the cached child list. + [item setNumChildren:[itemChildren count] isExpandable:isExpandable cacheVersion:mCacheVersion]; + [item setChildren:itemChildren]; +} + +- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem +{ nsCOMPtr propertyResource; mRDFService->GetResource([inPropertyURI UTF8String], getter_AddRefs(propertyResource)); @@ -378,38 +449,20 @@ #if DEBUG NSLog(@"ValueNode is null in RDF objectValueForTableColumn"); #endif - return; + return @""; } nsCOMPtr valueLiteral(do_QueryInterface(valueNode)); if (!valueLiteral) - return; + return @""; - valueLiteral->GetValue(outResult); + const PRUnichar* value = NULL; + valueLiteral->GetValueConst(&value); + if (value) + return [NSString stringWithCharacters:value length:nsCRT::strlen(value)]; + + return @""; } -@end - -@implementation RDFOutlineViewItem - -- (void) dealloc -{ - NS_IF_RELEASE(mResource); - [super dealloc]; -} - -- (nsIRDFResource*) resource -{ - NS_IF_ADDREF(mResource); - return mResource; -} - -- (void) setResource: (nsIRDFResource*) aResource -{ - nsIRDFResource* oldResource = mResource; - NS_IF_ADDREF(mResource = aResource); - NS_IF_RELEASE(oldResource); -} - @end diff --git a/chimera/src/history/HistoryDataSource.h b/chimera/src/history/HistoryDataSource.h index ac3e29f437b..e69de29bb2d 100644 --- a/chimera/src/history/HistoryDataSource.h +++ b/chimera/src/history/HistoryDataSource.h @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Ben Goodger (Original Author) - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import - -#import "RDFOutlineViewDataSource.h" - -class nsAString; -class HistoryDataSourceObserver; - -@class BrowserWindowController; - -@interface HistoryDataSource : RDFOutlineViewDataSource -{ - HistoryDataSourceObserver* mObserver; // STRONG ref, should be nsCOMPtr but can't - IBOutlet BrowserWindowController* mBrowserWindowController; -} - -// overridden to create a attributed string with icon --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem; - -- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem; - --(void) enableObserver; --(void) disableObserver; - --(IBAction)openHistoryItem: (id)aSender; --(IBAction)deleteHistoryItems: (id)aSender; - -@end diff --git a/chimera/src/history/HistoryDataSource.mm b/chimera/src/history/HistoryDataSource.mm index f1d040f99df..52a7a4bf7c3 100644 --- a/chimera/src/history/HistoryDataSource.mm +++ b/chimera/src/history/HistoryDataSource.mm @@ -63,33 +63,29 @@ class HistoryDataSourceObserver : public nsIRDFObserver { public: - HistoryDataSourceObserver(NSOutlineView* outlineView) : - mOutlineView(outlineView), mEnabled(false) + HistoryDataSourceObserver(HistoryDataSource* dataSource) + : mHistoryDataSource(dataSource) { NS_INIT_ISUPPORTS(); } - virtual ~HistoryDataSourceObserver() { } ; + virtual ~HistoryDataSourceObserver() { } NS_DECL_ISUPPORTS - NS_IMETHODIMP OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) ; - NS_IMETHODIMP OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) { return NS_OK; } + NS_IMETHOD OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*); + NS_IMETHOD OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*); - NS_IMETHODIMP OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) + NS_IMETHOD OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) { return NS_OK; } - NS_IMETHODIMP OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*); + NS_IMETHOD OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*); - NS_IMETHODIMP BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; } - NS_IMETHODIMP EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; } - - void Enable() { mEnabled = true; } - void Disable() { mEnabled = false; } + NS_IMETHOD BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; } + NS_IMETHOD EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; } private: - NSOutlineView* mOutlineView; - bool mEnabled; + HistoryDataSource* mHistoryDataSource; }; NS_IMPL_ISUPPORTS1(HistoryDataSourceObserver, nsIRDFObserver) @@ -105,15 +101,30 @@ NS_IMETHODIMP HistoryDataSourceObserver::OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource* aProperty, nsIRDFNode*) { - if(mEnabled) { - const char* p; - aProperty->GetValueConst(&p); - if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) - [mOutlineView reloadData]; - } + const char* p; + aProperty->GetValueConst(&p); + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + return NS_OK; } +// +// OnUnassert +// +// This gets called on redirects, when nsGlobalHistory::RemovePage is called. +// +NS_IMETHODIMP +HistoryDataSourceObserver::OnUnassert(nsIRDFDataSource*, nsIRDFResource*, + nsIRDFResource* aProperty, nsIRDFNode*) +{ + const char* p; + aProperty->GetValueConst(&p); + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + + return NS_OK; +} // // OnChange @@ -125,12 +136,12 @@ NS_IMETHODIMP HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource* aProperty, nsIRDFNode*, nsIRDFNode*) { - if(mEnabled) { - const char* p; - aProperty->GetValueConst(&p); - if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) - [mOutlineView reloadData]; - } + const char* p; + aProperty->GetValueConst(&p); + + if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0) + [mHistoryDataSource setNeedsRefresh:YES]; + return NS_OK; } @@ -138,7 +149,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, @interface HistoryDataSource(Private) -- (void)cleanup; +- (void)cleanupHistory; @end @@ -146,12 +157,12 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, - (void) dealloc { - [self cleanup]; + [self cleanupHistory]; [super dealloc]; } // "non-virtual" cleanup method -- safe to call from dealloc. -- (void)cleanup +- (void)cleanupHistory { if (mDataSource && mObserver) { @@ -163,7 +174,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, // "virtual" method; called from superclass - (void)cleanupDataSource { - [self cleanup]; + [self cleanupHistory]; [super cleanupDataSource]; } @@ -181,7 +192,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NS_ASSERTION(mRDFService, "Uh oh, RDF service not loaded in parent class"); - if ( !mDataSource ) { + if ( !mDataSource ) + { // Get the Global History DataSource mRDFService->GetDataSource("rdf:history", &mDataSource); // Get the Date Folder Root @@ -191,14 +203,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, [mOutlineView setDoubleAction: @selector(openHistoryItem:)]; [mOutlineView setDeleteAction: @selector(deleteHistoryItems:)]; - mObserver = new HistoryDataSourceObserver(mOutlineView); + mObserver = new HistoryDataSourceObserver(self); if ( mObserver ) { NS_ADDREF(mObserver); mDataSource->AddObserver(mObserver); } [mOutlineView reloadData]; } - else { + else + { // everything is loaded, but we have to refresh our tree otherwise // changes that took place while the drawer was closed won't be noticed [mOutlineView reloadData]; @@ -207,18 +220,41 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NS_ASSERTION(mDataSource, "Uh oh, History RDF Data source not created"); } -- (void) enableObserver +- (void)enableObserver { - if ( mObserver ) - mObserver->Enable(); + mUpdatesEnabled = YES; } --(void) disableObserver +-(void)disableObserver { - if ( mObserver ) - mObserver->Disable(); + mUpdatesEnabled = NO; } +- (void)setNeedsRefresh:(BOOL)needsRefresh +{ + mNeedsRefresh = needsRefresh; +} + +- (BOOL)needsRefresh +{ + return mNeedsRefresh; +} + +- (void)refresh +{ + if (mNeedsRefresh) + { + [self invalidateCachedItems]; + if (mUpdatesEnabled) + { + // this can be very slow! See bug 180109. + //NSLog(@"history reload started"); + [self reloadDataForItem:nil reloadChildren:NO]; + //NSLog(@"history reload done"); + } + mNeedsRefresh = NO; + } +} // // createCellContents:withColumn:byItem @@ -226,31 +262,29 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, // override to create an NSAttributedString instead of just the string with the // given text. We add an icon and adjust the positioning of the text w/in the cell // --(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem +-(id) createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem { - NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init]; - - //Set cell's textual contents - [cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString:inValue]]; + if ([inValue length] == 0) + inValue = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem]; - if ([inColumn isEqualToString: @"http://home.netscape.com/NC-rdf#Name"]) { - NSMutableAttributedString *attachmentAttrString = nil; - NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; - NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - NSCell *attachmentAttrStringCell; + NSMutableAttributedString *cellValue = [[[NSMutableAttributedString alloc] initWithString:inValue] autorelease]; + + if ([inColumn isEqualToString:@"http://home.netscape.com/NC-rdf#Name"]) + { + NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil]; + NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper]; - //Create an attributed string to hold the empty attachment, then release the components. - attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain]; + // Create an attributed string to hold the empty attachment, then release the components. + NSMutableAttributedString *attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment]; [textAttachment release]; [fileWrapper release]; //Get the cell of the text attachment. - attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute: + NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute: NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell]; - if ([self outlineView:mOutlineView isItemExpandable:inItem]) { + if ([self outlineView:mOutlineView isItemExpandable:inItem]) [attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]]; - } else [attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]]; @@ -298,11 +332,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, id item = [toDrag objectAtIndex: 0]; // if we have just one item, we add some more flavours - nsXPIDLString urlLiteral, nameLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item result:getter_Copies(nameLiteral)]; - NSString* url = [NSString stringWith_nsAString: urlLiteral]; - NSString* title = [NSString stringWith_nsAString: nameLiteral]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; + NSString* title = [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item]; NSString *cleanedTitle = [title stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "]; [pboard declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:self]; @@ -340,11 +371,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, return; } - nsXPIDLString urlLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - // get uri - NSString* url = [NSString stringWith_nsAString: urlLiteral]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; [[mBrowserWindowController getBrowserWrapper] loadURI: url referrer: nil flags: NSLoadFlagsNone activate:YES]; } @@ -376,14 +404,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, index = [currIndex intValue]; RDFOutlineViewItem* item = [mOutlineView itemAtRow: index]; if (![mOutlineView isExpandable: item]) { - nsXPIDLString urlLiteral; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)]; - history->RemovePage(NS_ConvertUCS2toUTF8(urlLiteral).get()); + NSString* urlString = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item]; + history->RemovePage([urlString UTF8String]); } } history->EndBatchUpdate(); if ( clearSelectionWhenDone ) [mOutlineView deselectAll:self]; + + [self invalidateCachedItems]; [mOutlineView reloadData]; // necessary or the outline is really horked } } @@ -402,9 +431,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*, NSString* pageTitle = [super outlineView:outlineView tooltipStringForItem:inItem]; // append url - nsXPIDLString literalValue; - [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem result:getter_Copies(literalValue)]; - return [NSString stringWithFormat:@"%@\n%@", pageTitle, [NSString stringWith_nsAString:literalValue]]; + NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem]; + return [NSString stringWithFormat:@"%@\n%@", pageTitle, [url stringByTruncatingTo:80 at:kTruncateAtEnd]]; } return nil; } diff --git a/chimera/src/includes/ChimeraUIConstants.h b/chimera/src/includes/ChimeraUIConstants.h index b96c6e40dd7..e69de29bb2d 100644 --- a/chimera/src/includes/ChimeraUIConstants.h +++ b/chimera/src/includes/ChimeraUIConstants.h @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Simon Fraser - * - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - - -// Put UI constants (menu item tags etc) in this file to reduce the -// chance of conflicts. - -// Go menu - -// the tag of the separator after which to insert history menu items -const int kRendezvousRelatedItemTag = 3000; -const int kDividerTag = 4000; - - -// Bookmarks menu - -// the tag of the separator after which to insert bookmark items -const int kBookmarksDividerTag = -1; diff --git a/chimera/src/preferences/PreferenceManager.h b/chimera/src/preferences/PreferenceManager.h index 8273aca7a71..e69de29bb2d 100644 --- a/chimera/src/preferences/PreferenceManager.h +++ b/chimera/src/preferences/PreferenceManager.h @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: NPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Netscape Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2002 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the NPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the NPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#import -#import - -class nsIPref; - -@interface PreferenceManager : NSObject -{ - NSUserDefaults* mDefaults; - ICInstance mInternetConfig; - nsIPref* mPrefs; -} - -+ (PreferenceManager *)sharedInstance; - -- (id) init; -- (void) dealloc; -- (BOOL) initInternetConfig; -- (BOOL) initMozillaPrefs; -- (void) syncMozillaPrefs; -- (void) savePrefsFile; - -- (NSString *) getICStringPref:(ConstStr255Param) prefKey; -- (NSString *) homePage:(BOOL) checkStartupPagePref; -- (NSString *) searchPage; - -- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess; -- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess; -- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess; -- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess; - -- (void)setPref:(const char*)prefName toString:(NSString*)value; -- (void)setPref:(const char*)prefName toInt:(int)value; -- (void)setPref:(const char*)prefName toBoolean:(BOOL)value; - -@end diff --git a/chimera/src/preferences/PreferenceManager.mm b/chimera/src/preferences/PreferenceManager.mm index 18cf20c5680..8378bd39d82 100644 --- a/chimera/src/preferences/PreferenceManager.mm +++ b/chimera/src/preferences/PreferenceManager.mm @@ -38,6 +38,7 @@ #import #import + #import "PreferenceManager.h" #import "UserDefaults.h" #import "CHBrowserService.h" @@ -60,11 +61,23 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count); @interface PreferenceManager(PreferenceManagerPrivate) ++ (PreferenceManager *) sharedInstanceDontCreate; + - (void)registerNotificationListener; - (void)termEmbedding: (NSNotification*)aNotification; - (void)xpcomTerminate: (NSNotification*)aNotification; +- (void)configureProxies; +- (BOOL)updateOneProxy:(NSDictionary*)configDict + protocol:(NSString*)protocol + proxyEnableKey:(NSString*)enableKey + proxyURLKey:(NSString*)urlKey + proxyPortKey:(NSString*)portKey; + +- (void)registerForProxyChanges; +- (BOOL)readSystemProxySettings; + @end @@ -76,7 +89,7 @@ static PreferenceManager* gSharedInstance = nil; static BOOL gMadePrefManager; #endif -+ (PreferenceManager *) sharedInstance ++ (PreferenceManager *)sharedInstance { if (!gSharedInstance) { @@ -88,13 +101,20 @@ static BOOL gMadePrefManager; gSharedInstance = [[PreferenceManager alloc] init]; } - return gSharedInstance; + return gSharedInstance; +} + ++ (PreferenceManager *)sharedInstanceDontCreate +{ + return gSharedInstance; } - (id) init { if ((self = [super init])) { + mRunLoopSource = NULL; + [self registerNotificationListener]; if ([self initInternetConfig] == NO) { @@ -115,6 +135,8 @@ static BOOL gMadePrefManager; - (void) dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (self == gSharedInstance) + gSharedInstance = nil; [super dealloc]; } @@ -123,6 +145,13 @@ static BOOL gMadePrefManager; ::ICStop(mInternetConfig); mInternetConfig = nil; NS_IF_RELEASE(mPrefs); + // remove our runloop observer + if (mRunLoopSource) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes); + CFRelease(mRunLoopSource); + mRunLoopSource = NULL; + } } - (void)xpcomTerminate: (NSNotification*)aNotification @@ -145,14 +174,14 @@ static BOOL gMadePrefManager; object: nil]; } -- (void) savePrefsFile +- (void)savePrefsFile { nsCOMPtr prefsService = do_GetService(NS_PREF_CONTRACTID); if (prefsService) prefsService->SavePrefFile(nsnull); } -- (BOOL) initInternetConfig +- (BOOL)initInternetConfig { OSStatus error; error = ::ICStart(&mInternetConfig, 'CHIM'); @@ -164,7 +193,7 @@ static BOOL gMadePrefManager; return YES; } -- (BOOL) initMozillaPrefs +- (BOOL)initMozillaPrefs { #ifdef _BUILD_STATIC_BIN @@ -246,15 +275,8 @@ static BOOL gMadePrefManager; return YES; } -- (void) syncMozillaPrefs +- (void)syncMozillaPrefs { - CFArrayRef cfArray; - CFDictionaryRef cfDictionary; - CFNumberRef cfNumber; - CFStringRef cfString; - char strbuf[1024]; - int numbuf; - if (!mPrefs) { NSLog(@"Mozilla prefs not set up successfully"); return; @@ -268,19 +290,101 @@ static BOOL gMadePrefManager; // fix up the cookie prefs. If 'p3p' or 'accept foreign cookies' are on, remap them to // something that chimera can deal with. PRInt32 acceptCookies = 0; - static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior"; + static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior"; mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies); - if ( acceptCookies == 1 ) { // accept foreign cookies, assume off + if ( acceptCookies == 1 ) { // accept foreign cookies, assume off acceptCookies = 2; - mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); - } + mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); + } else if ( acceptCookies == 3 ) { // p3p, assume all cookies on acceptCookies = 0; - mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); + mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies); } - + + [self configureProxies]; +} + +#pragma mark - + +- (void)configureProxies +{ + [self readSystemProxySettings]; + [self registerForProxyChanges]; +} + +static void SCProxiesChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void * /* info */) +{ + PreferenceManager* prefsManager = [PreferenceManager sharedInstanceDontCreate]; + [prefsManager readSystemProxySettings]; +#if DEBUG + NSLog(@"Updating proxies"); +#endif +} + +- (void)registerForProxyChanges +{ + if (mRunLoopSource) // don't register twice + return; + + SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL}; + + SCDynamicStoreRef dynamicStoreRef = SCDynamicStoreCreate(NULL, CFSTR("ChimeraProxiesNotification"), SCProxiesChangedCallback, &context); + if (dynamicStoreRef) + { + CFStringRef proxyIdentifier = SCDynamicStoreKeyCreateProxies(NULL); + CFArrayRef keyList = CFArrayCreate(NULL, (const void **)&proxyIdentifier, 1, &kCFTypeArrayCallBacks); + + Boolean set = SCDynamicStoreSetNotificationKeys(dynamicStoreRef, keyList, NULL); + if (set) + { + mRunLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, dynamicStoreRef, 0); + if (mRunLoopSource) + { + CFRunLoopAddSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes); + // we keep the ref to the source, so that we can remove it when the prefs manager is cleaned up. + } + } + + CFRelease(proxyIdentifier); + CFRelease(keyList); + CFRelease(dynamicStoreRef); + } +} + +- (BOOL)updateOneProxy:(NSDictionary*)configDict + protocol:(NSString*)protocol + proxyEnableKey:(NSString*)enableKey + proxyURLKey:(NSString*)urlKey + proxyPortKey:(NSString*)portKey +{ + BOOL gotProxy = NO; + + BOOL enabled = (BOOL)[[configDict objectForKey:enableKey] intValue]; + if (enabled) + { + NSString* protocolProxy = [configDict objectForKey:urlKey]; + int proxyPort = [[configDict objectForKey:portKey] intValue]; + if ([protocolProxy length] > 0 && proxyPort != 0) + { + [self setPref:[[NSString stringWithFormat:@"network.proxy.%@", protocol] cString] toString:protocolProxy]; + [self setPref:[[NSString stringWithFormat:@"network.proxy.%@_port", protocol] cString] toInt:proxyPort]; + gotProxy = YES; + } + } + + return gotProxy; +} + +- (BOOL)readSystemProxySettings +{ + BOOL usingProxies = NO; + + PRInt32 proxyType, newProxyType; + mPrefs->GetIntPref("network.proxy.type", &proxyType); + newProxyType = proxyType; + if (proxyType == 0 || proxyType == 1) + { // get proxies from SystemConfiguration - mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies mPrefs->ClearUserPref("network.proxy.http"); mPrefs->ClearUserPref("network.proxy.http_port"); mPrefs->ClearUserPref("network.proxy.ssl"); @@ -293,94 +397,66 @@ static BOOL gMadePrefManager; mPrefs->ClearUserPref("network.proxy.socks_port"); mPrefs->ClearUserPref("network.proxy.no_proxies_on"); - if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.http", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.http_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } + NSDictionary* proxyConfigDict = (NSDictionary*)SCDynamicStoreCopyProxies(NULL); + if (proxyConfigDict) + { + BOOL gotAProxy = NO; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"http" + proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPEnable + proxyURLKey:(NSString*)kSCPropNetProxiesHTTPProxy + proxyPortKey:(NSString*)kSCPropNetProxiesHTTPPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ssl" + proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPSEnable + proxyURLKey:(NSString*)kSCPropNetProxiesHTTPSProxy + proxyPortKey:(NSString*)kSCPropNetProxiesHTTPSPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ftp" + proxyEnableKey:(NSString*)kSCPropNetProxiesFTPEnable + proxyURLKey:(NSString*)kSCPropNetProxiesFTPProxy + proxyPortKey:(NSString*)kSCPropNetProxiesFTPPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"gopher" + proxyEnableKey:(NSString*)kSCPropNetProxiesGopherEnable + proxyURLKey:(NSString*)kSCPropNetProxiesGopherProxy + proxyPortKey:(NSString*)kSCPropNetProxiesGopherPort]; + + gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"socks" + proxyEnableKey:(NSString*)kSCPropNetProxiesSOCKSEnable + proxyURLKey:(NSString*)kSCPropNetProxiesSOCKSProxy + proxyPortKey:(NSString*)kSCPropNetProxiesSOCKSPort]; + + if (gotAProxy) + { + newProxyType = 1; + + NSArray* exceptions = [proxyConfigDict objectForKey:(NSString*)kSCPropNetProxiesExceptionsList]; + if (exceptions) + { + NSString* sitesList = [exceptions componentsJoinedByString:@", "]; + if ([sitesList length] > 0) + [self setPref:"network.proxy.no_proxies_on" toString:sitesList]; } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.ssl", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.ssl_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.ftp", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.ftp_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.gopher", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.gopher_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSEnable, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) { - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.socks", strbuf); - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) { - if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) { - mPrefs->SetIntPref("network.proxy.socks_port", numbuf); - } - mPrefs->SetIntPref("network.proxy.type", 1); - } - } - } - } - if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesExceptionsList, (const void **)&cfArray) == TRUE) { - cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", ")); - if (CFStringGetLength (cfString) > 0) { - if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) { - mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf); - } - } - } - CFRelease (cfDictionary); + usingProxies = YES; + } + else + { + newProxyType = 0; + } + + [proxyConfigDict release]; } + + if (newProxyType != proxyType) + mPrefs->SetIntPref("network.proxy.type", 1); + } + + return usingProxies; } +#pragma mark - + - (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess { NSString *prefValue = @""; @@ -406,16 +482,16 @@ static BOOL gMadePrefManager; { // colors are stored in HTML-like #FFFFFF strings NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess]; - NSColor* returnColor = [NSColor blackColor]; + NSColor* returnColor = [NSColor blackColor]; if ([colorString hasPrefix:@"#"] && [colorString length] == 7) { unsigned int redInt, greenInt, blueInt; sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt); - float redFloat = ((float)redInt / 255.0); - float greenFloat = ((float)greenInt / 255.0); - float blueFloat = ((float)blueInt / 255.0); + float redFloat = ((float)redInt / 255.0); + float greenFloat = ((float)greenInt / 255.0); + float blueFloat = ((float)blueInt / 255.0); returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f]; } @@ -548,7 +624,7 @@ static BOOL gMadePrefManager; mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]); } else { - homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL]; + homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL]; } if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])