1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code, released
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2000
21 * the Initial Developer. All Rights Reserved.
24 * Daniel Veditz <dveditz@netscape.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
42 #include "nsRegisterItem.h"
43 #include "nsInstallResources.h"
44 #include "nsNetUtil.h"
45 #include "nsXPIDLString.h"
46 #include "nsReadableUtils.h"
47 #include "nsInstallTrigger.h"
48 #include "nsIChromeRegistry.h"
49 #include "nsIDirectoryService.h"
50 #include "nsDirectoryServiceDefs.h"
51 #include "nsAppDirectoryServiceDefs.h"
52 #include "nsNativeCharsetUtils.h"
54 nsRegisterItem:: nsRegisterItem( nsInstall
* inInstall
,
58 : nsInstallObject(inInstall
), mChrome(chrome
), mChromeType(chromeType
), mPath(path
)
60 MOZ_COUNT_CTOR(nsRegisterItem
);
64 nsRegisterItem::~nsRegisterItem()
66 MOZ_COUNT_DTOR(nsRegisterItem
);
74 hack_nsIFile2URL(nsIFile
* file
, char * *aURL
)
78 rv
= file
->GetNativePath(ePath
);
79 if (NS_FAILED(rv
)) return rv
;
80 #if defined(XP_WIN) || defined(XP_OS2)
81 // Replace \ with / to convert to an url
83 ePath
.BeginWriting(s
);
86 // We need to call IsDBCSLeadByte because
87 // Japanese windows can have 0x5C in the sencond byte
88 // of a Japanese character, for example 0x8F 0x5C is
89 // one Japanese character
90 if(::IsDBCSLeadByte(*s
) && *(s
+1) != nsnull
) {
99 // Escape the path with the directory mask
100 nsCAutoString
tmp(ePath
);
101 tmp
.ReplaceChar(":", '|');
102 nsCAutoString
escPath("file://");
104 // rv = nsURLEscape(ePath,nsIIOService::url_Directory + nsIIOService::url_Forced, escPath);
105 // if (NS_SUCCEEDED(rv)) {
107 rv
= file
->IsDirectory(&dir
);
108 if (NS_SUCCEEDED(rv
) && dir
&& escPath
[escPath
.Length() - 1] != '/') {
109 // make sure we have a trailing slash
112 *aURL
= ToNewCString(escPath
);
113 if (*aURL
== nsnull
) {
114 return NS_ERROR_OUT_OF_MEMORY
;
120 void nsRegisterItem::LogErrorWithFilename(const nsAString
& aMessage
, nsresult code
, nsILocalFile
* localFile
)
123 nsAutoString unipath
;
125 LogError(aMessage
, code
);
126 localFile
->GetNativePath(path
);
127 if(NS_SUCCEEDED(NS_CopyNativeToUnicode(path
, unipath
)))
128 mInstall
->LogComment(unipath
);
131 void nsRegisterItem::LogError(const nsAString
& aMessage
, nsresult code
)
133 char resultString
[12];
135 PR_snprintf(resultString
, 12, "0x%lx", code
);
136 mInstall
->LogComment(aMessage
+ NS_LITERAL_STRING(" - nsresult code: ") +
137 NS_ConvertASCIItoUTF16(resultString
));
140 PRInt32
nsRegisterItem::Prepare()
142 // The chrome must exist
144 nsresult rv
= mChrome
->Exists(&exists
);
146 return nsInstall::UNEXPECTED_ERROR
;
148 return nsInstall::DOES_NOT_EXIST
;
151 // Are we dealing with a directory (flat chrome) or an archive?
153 rv
= mChrome
->IsDirectory(&isDir
);
155 return nsInstall::UNEXPECTED_ERROR
;
158 // Can we construct a resource: URL or do we need a file: URL instead?
159 // find the xpcom directory and see if mChrome is a child
160 PRBool isChild
= PR_FALSE
;
161 mProgDir
= nsSoftwareUpdate::GetProgramDirectory();
164 // not in the wizard, so ask the directory service where it is
165 nsCOMPtr
<nsIProperties
> dirService(
166 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
));
169 NS_ASSERTION(dirService
,"directory service lied to us");
170 rv
= dirService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
,
171 NS_GET_IID(nsIFile
), getter_AddRefs(mProgDir
));
174 if (NS_SUCCEEDED(rv
))
176 NS_ASSERTION(mProgDir
,"NS_SUCCESS but no mProgDir");
177 rv
= mProgDir
->Contains(mChrome
, PR_TRUE
, &isChild
);
179 return nsInstall::UNEXPECTED_ERROR
;
182 return nsInstall::UNEXPECTED_ERROR
;
185 // Either way we need the file: URL to the chrome
186 nsXPIDLCString localURL
;
187 rv
= GetURLFromIFile( mChrome
, getter_Copies(localURL
) );
189 return nsInstall::UNEXPECTED_ERROR
;
191 // see what kind of URL we have to construct
194 // Not relative so use the file:// URL we got above
195 PRInt32 urlLen
= strlen(localURL
) + mPath
.Length();
199 // "flat" chrome, urlLen is suffient
200 mURL
.SetCapacity( urlLen
);
204 // archive, add room for jar: syntax (over by one, but harmless)
205 mURL
.SetCapacity( urlLen
+ sizeof("jar:") + sizeof('!') );
208 mURL
.Append(localURL
);
212 // we can construct a resource: URL to chrome in a subdir
213 nsXPIDLCString binURL
;
214 rv
= GetURLFromIFile( mProgDir
, getter_Copies(binURL
) );
216 return nsInstall::UNEXPECTED_ERROR
;
218 PRInt32 binLen
= strlen(binURL
);
219 const char *subURL
= localURL
+ binLen
;
220 PRInt32 padding
= sizeof("resource:/") + sizeof("jar:!/");
222 mURL
.SetCapacity( strlen(subURL
) + mPath
.Length() + padding
);
227 mURL
.Append("resource:/");
234 // need jar: URL closing bang-slash
239 // Necko should already slash-terminate directory file:// URLs
240 NS_ASSERTION(mURL
[mURL
.Length()-1] == '/', "Necko changed the rules");
243 // add on "extra" subpath to new content.rdf
246 return nsInstall::SUCCESS
;
249 PRInt32
nsRegisterItem::Complete()
252 PRInt32 result
= nsInstall::SUCCESS
;
253 CHROMEREG_IFACE
* reg
= mInstall
->GetChromeRegistry();
255 PRBool isProfile
= mChromeType
& CHROME_PROFILE
;
258 if ( reg
&& !(mChromeType
& CHROME_DELAYED
) )
261 nsCOMPtr
<nsIURI
> baseuri
;
262 rv
= NS_NewURI(getter_AddRefs(baseuri
), mURL
);
264 LogError(NS_LITERAL_STRING("NS_NewURI failed."), rv
);
267 nsCOMPtr
<nsIURI
> manifesturi
;
268 rv
= NS_NewURI(getter_AddRefs(manifesturi
),
269 NS_LITERAL_CSTRING("resource:///chrome/xpinstall.manifest"));
271 LogError(NS_LITERAL_STRING("NS_NewURI failed."), rv
);
274 PRBool skinOnly
= (mChromeType
& CHROME_ALL
) == CHROME_SKIN
;
275 rv
= reg
->ProcessContentsManifest(baseuri
, manifesturi
,
279 LogError(NS_LITERAL_STRING("ProcessContentsManifest failed."), rv
);
281 reg
->CheckForNewChrome();
285 // We can register right away
286 if (mChromeType
& CHROME_SKIN
)
287 rv
= reg
->InstallSkin(mURL
.get(), isProfile
, PR_TRUE
);
289 LogError(NS_LITERAL_STRING("InstallSkin() failed."), rv
);
292 if (NS_SUCCEEDED(rv
) && (mChromeType
& CHROME_LOCALE
))
293 rv
= reg
->InstallLocale(mURL
.get(), isProfile
);
295 LogError(NS_LITERAL_STRING("InstallLocale() failed."), rv
);
298 if (NS_SUCCEEDED(rv
) && (mChromeType
& CHROME_CONTENT
))
299 rv
= reg
->InstallPackage(mURL
.get(), isProfile
);
301 LogError(NS_LITERAL_STRING("InstallPackage() failed."), rv
);
307 // Either script asked for delayed chrome or we can't find
308 // the chrome registry to do it now.
310 // construct a reference to the magic file
311 PRFileDesc
* fd
= nsnull
;
312 nsCOMPtr
<nsIFile
> tmp
;
313 PRBool bExists
= PR_FALSE
;
314 if (!nsSoftwareUpdate::GetProgramDirectory()) // not in the stub installer
316 nsCOMPtr
<nsIProperties
> directoryService
=
317 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
319 LogError(NS_LITERAL_STRING("failed to get directory service."), rv
);
321 if (NS_SUCCEEDED(rv
) && directoryService
)
323 rv
= directoryService
->Get(NS_APP_CHROME_DIR
,
325 getter_AddRefs(tmp
));
328 LogError(NS_LITERAL_STRING("failed get application chrome directory."), rv
);
329 result
= nsInstall::CHROME_REGISTRY_ERROR
;
336 rv
= nsSoftwareUpdate::GetProgramDirectory()->Clone(getter_AddRefs(tmp
));
338 if (NS_SUCCEEDED(rv
))
340 tmp
->AppendNative(INSTALL_CHROME_DIR
);
342 LogError(NS_LITERAL_STRING("failed to clone program directory. (not critical)"), rv
);
345 nsCOMPtr
<nsILocalFile
> startupFile( do_QueryInterface(tmp
, &rv
) );
347 if (NS_SUCCEEDED(rv
))
349 rv
= startupFile
->Exists(&bExists
);
352 LogErrorWithFilename(NS_LITERAL_STRING("directory existance check failed."), rv
, startupFile
);
354 if (NS_SUCCEEDED(rv
) && !bExists
)
355 rv
= startupFile
->Create(nsIFile::DIRECTORY_TYPE
, 0755);
356 if (NS_SUCCEEDED(rv
))
358 rv
= startupFile
->AppendNative(NS_LITERAL_CSTRING("installed-chrome.txt"));
359 if (NS_SUCCEEDED(rv
))
361 rv
= startupFile
->OpenNSPRFileDesc(
362 PR_CREATE_FILE
| PR_WRONLY
,
367 LogErrorWithFilename(NS_LITERAL_STRING("opening of installed-chrome.txt failed."), rv
, startupFile
);
370 LogError(NS_LITERAL_STRING("String append failed."), rv
);
373 LogErrorWithFilename(NS_LITERAL_STRING("startup directory creation failed."), rv
, startupFile
);
377 if ( NS_SUCCEEDED(rv
) && fd
)
379 PR_Seek(fd
, 0, PR_SEEK_END
);
380 const char* location
= (mChromeType
& CHROME_PROFILE
) ? "profile" : "install";
382 if (NS_SUCCEEDED(rv
)/* && path*/)
384 PRInt32 written
, actual
;
385 char* installStr
= nsnull
;
387 // this looks redundant, but a single registerChrome()
388 // call can register all three types.
389 if (mChromeType
& CHROME_SKIN
)
391 installStr
= PR_smprintf("skin,%s,url,%s\n",
392 location
, mURL
.get());
395 actual
= strlen(installStr
);
396 written
= PR_Write(fd
, installStr
, actual
);
397 if ( written
!= actual
)
399 LogErrorWithFilename(NS_LITERAL_STRING("writing to installed-chrome.txt failed."), rv
, startupFile
);
400 result
= nsInstall::CHROME_REGISTRY_ERROR
;
402 PR_smprintf_free(installStr
);
405 result
= nsInstall::OUT_OF_MEMORY
;
408 if (mChromeType
& CHROME_LOCALE
)
410 installStr
= PR_smprintf("locale,%s,url,%s\n",
411 location
, mURL
.get());
414 actual
= strlen(installStr
);
415 written
= PR_Write(fd
, installStr
, actual
);
416 if ( written
!= actual
)
418 LogErrorWithFilename(NS_LITERAL_STRING("writing to installed-chrome.txt failed."), rv
, startupFile
);
419 result
= nsInstall::CHROME_REGISTRY_ERROR
;
421 PR_smprintf_free(installStr
);
424 result
= nsInstall::OUT_OF_MEMORY
;
427 if (mChromeType
& CHROME_CONTENT
)
429 installStr
= PR_smprintf("content,%s,url,%s\n",
430 location
, mURL
.get());
433 actual
= strlen(installStr
);
434 written
= PR_Write(fd
, installStr
, actual
);
435 if ( written
!= actual
)
437 LogErrorWithFilename(NS_LITERAL_STRING("writing to installed-chrome.txt failed."), rv
, startupFile
);
438 result
= nsInstall::CHROME_REGISTRY_ERROR
;
440 PR_smprintf_free(installStr
);
443 result
= nsInstall::OUT_OF_MEMORY
;
449 // app-chrome.manifest is not regenerated if it exists
450 rv
= startupFile
->SetNativeLeafName(NS_LITERAL_CSTRING("app-chrome.manifest"));
451 if (NS_SUCCEEDED(rv
))
452 startupFile
->Remove(PR_FALSE
);
457 LogError(NS_LITERAL_STRING("opening of installed-chrome.txt failed."), rv
);
458 result
= nsInstall::CHROME_REGISTRY_ERROR
;
464 LogError(NS_LITERAL_STRING("Failed to register chrome."), rv
);
465 result
= nsInstall::CHROME_REGISTRY_ERROR
;
471 void nsRegisterItem::Abort()
476 char* nsRegisterItem::toString()
478 char* rsrcVal
= nsnull
;
483 char* buffer
= new char[1024];
488 switch (mChromeType
& CHROME_ALL
)
491 rsrcVal
= mInstall
->GetResourcedString(
492 NS_LITERAL_STRING("RegSkin"));
495 rsrcVal
= mInstall
->GetResourcedString(
496 NS_LITERAL_STRING("RegLocale"));
499 rsrcVal
= mInstall
->GetResourcedString(
500 NS_LITERAL_STRING("RegContent"));
503 rsrcVal
= mInstall
->GetResourcedString(
504 NS_LITERAL_STRING("RegPackage"));
510 PR_snprintf(buffer
, 1024, rsrcVal
, mURL
.get());
511 nsCRT::free(rsrcVal
);
519 nsRegisterItem::CanUninstall()
525 nsRegisterItem::RegisterPackageNode()
531 nsRegisterItem::GetURLFromIFile(nsIFile
* aFile
, char** aOutURL
)
533 if (!aFile
|| !aOutURL
)
535 NS_WARNING("bogus arg passed to nsRegisterItem::GetURLFromIFile()");
536 return NS_ERROR_NULL_POINTER
;
540 // try to use Necko to create the URL; if that fails (as
541 // it will for the install wizards which don't have Necko)
542 // then use warren's local hack.
545 nsresult rv
= NS_GetURLSpecFromFile(aFile
, spec
);
547 rv
= hack_nsIFile2URL(aFile
, aOutURL
);
549 *aOutURL
= ToNewCString(spec
);
551 rv
= NS_ERROR_OUT_OF_MEMORY
;