Bug 661363 - Port bug 562753 (On upgrade, old win7 taskbar entries should have their app model id upgraded, based on install path) to Thunderbird. r=Standard8, sr=bienvenu

This commit is contained in:
Siddharth Agarwal 2011-06-09 11:44:05 -07:00
Родитель 8f79905e29
Коммит 227725ff37
8 изменённых файлов: 238 добавлений и 41 удалений

Просмотреть файл

@ -46,6 +46,8 @@
#include "nsILocalFile.h"
#include "nsDirectoryServiceDefs.h"
#include "nsUnicharUtils.h"
#include "nsIWinTaskbar.h"
#include "nsISupportsPrimitives.h"
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
@ -63,7 +65,9 @@
#define REG_FAILED(val) \
(val != ERROR_SUCCESS)
NS_IMPL_ISUPPORTS1(nsWindowsShellService, nsIShellService)
#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
static nsresult
OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
@ -139,6 +143,126 @@ static SETTING gFeedSettings[] = {
{ MAKE_KEY_NAME1("feed", SOP), "", VAL_MAIL_OPEN, APP_PATH_SUBSTITUTION },
};
nsresult
GetHelperPath(nsAutoString& aPath)
{
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILocalFile> appHelper;
rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
NS_GET_IID(nsILocalFile),
getter_AddRefs(appHelper));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->Append(NS_LITERAL_STRING("uninstall"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->Append(NS_LITERAL_STRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
return appHelper->GetPath(aPath);
}
nsresult
LaunchHelper(nsAutoString& aPath, nsAutoString& aParams)
{
SHELLEXECUTEINFOW executeInfo = {0};
executeInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
executeInfo.hwnd = NULL;
executeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
executeInfo.lpDirectory = NULL;
executeInfo.lpFile = aPath.get();
executeInfo.lpParameters = aParams.get();
executeInfo.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&executeInfo))
// Block until the program exits
WaitForSingleObject(executeInfo.hProcess, INFINITE);
else
return NS_ERROR_ABORT;
// We're going to ignore errors here since there's nothing we can do about
// them, and helper.exe seems to return non-zero ret on success.
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::ShortcutMaintenance()
{
nsresult rv;
// Launch helper.exe so it can update the application user model ids on
// shortcuts in the user's taskbar and start menu. This keeps older pinned
// shortcuts grouped correctly after major updates. Note, we also do this
// through the upgrade installer script, however, this is the only place we
// have a chance to trap links created by users who do control the install/
// update process of the browser.
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
if (!taskbarInfo) // If we haven't built with win7 sdk features, this fails.
return NS_OK;
// Avoid if this isn't Win7+
PRBool isSupported = PR_FALSE;
taskbarInfo->GetAvailable(&isSupported);
if (!isSupported)
return NS_OK;
nsAutoString appId;
if (NS_FAILED(taskbarInfo->GetDefaultGroupId(appId)))
return NS_ERROR_UNEXPECTED;
NS_NAMED_LITERAL_CSTRING(prefName, "mail.taskbar.lastgroupid");
nsCOMPtr<nsIPrefService> prefs =
do_GetService(NS_PREFSERVICE_CONTRACTID);
if (!prefs)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIPrefBranch> prefBranch;
prefs->GetBranch(nsnull, getter_AddRefs(prefBranch));
if (!prefBranch)
return NS_ERROR_UNEXPECTED;
nsCOMPtr<nsISupportsString> prefString;
rv = prefBranch->GetComplexValue(prefName.get(),
NS_GET_IID(nsISupportsString),
getter_AddRefs(prefString));
if (NS_SUCCEEDED(rv)) {
nsAutoString version;
prefString->GetData(version);
if (!version.IsEmpty() && version.Equals(appId)) {
// We're all good, get out of here.
return NS_OK;
}
}
// Update the version in prefs
prefString =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
prefString->SetData(appId);
rv = prefBranch->SetComplexValue(prefName.get(),
NS_GET_IID(nsISupportsString),
prefString);
if (NS_FAILED(rv)) {
NS_WARNING("Couldn't set last user model id!");
return NS_ERROR_UNEXPECTED;
}
nsAutoString appHelperPath;
if (NS_FAILED(GetHelperPath(appHelperPath)))
return NS_ERROR_UNEXPECTED;
nsAutoString params;
params.AssignLiteral(" /UpdateShortcutAppUserModelIds");
return LaunchHelper(appHelperPath, params);
}
nsresult nsWindowsShellService::Init()
{
nsresult rv;
@ -202,24 +326,9 @@ nsWindowsShellService::IsDefaultClient(PRBool aStartupCheck, PRUint16 aApps, PRB
NS_IMETHODIMP
nsWindowsShellService::SetDefaultClient(PRBool aForAllUsers, PRUint16 aApps)
{
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILocalFile> appHelper;
rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(appHelper));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString appHelperPath;
rv = appHelper->GetPath(appHelperPath);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(GetHelperPath(appHelperPath)))
return NS_ERROR_FAILURE;
nsAutoString params;
if (aForAllUsers)
@ -236,25 +345,7 @@ nsWindowsShellService::SetDefaultClient(PRBool aForAllUsers, PRUint16 aApps)
params.AppendLiteral(" News");
}
SHELLEXECUTEINFOW executeInfo = {0};
executeInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
executeInfo.hwnd = NULL;
executeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
executeInfo.lpDirectory = NULL;
executeInfo.lpFile = appHelperPath.get();
executeInfo.lpParameters = params.get();
executeInfo.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&executeInfo))
// Block until the program exits
WaitForSingleObject(executeInfo.hProcess, INFINITE);
else
return NS_ERROR_ABORT;
// We're going to ignore errors here since there's nothing we can do about
// them, and helper.exe seems to return non-zero ret on success.
return NS_OK;
return LaunchHelper(appHelperPath, params);
}
NS_IMETHODIMP

Просмотреть файл

@ -38,7 +38,7 @@
#ifndef nsMailWinIntegration_h_
#define nsMailWinIntegration_h_
#include "nsIShellService.h"
#include "nsIWindowsShellService.h"
#include "nsIObserver.h"
#include "nsString.h"
@ -56,7 +56,7 @@ typedef struct {
PRInt32 flags;
} SETTING;
class nsWindowsShellService : public nsIShellService
class nsWindowsShellService : public nsIWindowsShellService
{
public:
nsWindowsShellService();
@ -65,6 +65,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSISHELLSERVICE
NS_DECL_NSIWINDOWSSHELLSERVICE
protected:
PRBool TestForDefault(SETTING aSettings[], PRInt32 aSize);

Просмотреть файл

@ -45,6 +45,6 @@ include $(DEPTH)/config/autoconf.mk
MODULE = shellservice
XPIDL_MODULE = shellservice
XPIDLSRCS = nsIShellService.idl
XPIDLSRCS = nsIShellService.idl nsIWindowsShellService.idl
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,48 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Shell Service.
*
* The Initial Developer of the Original Code is
* the Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Siddharth Agarwal <sid.bugzilla@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsIShellService.idl"
[scriptable, uuid(c6bcecde-6f2e-417c-bc30-466f560c3b51)]
interface nsIWindowsShellService : nsIShellService
{
/**
* Perform some Windows 7+ shortcut maintenance. This is called at program startup.
*/
void shortcutMaintenance();
};

Просмотреть файл

@ -61,6 +61,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "_taskbarService",
"@mozilla.org/windows-taskbar;1",
"nsIWinTaskbar");
XPCOMUtils.defineLazyServiceGetter(this, "_winShellService",
"@mozilla.org/mail/shell-service;1",
"nsIWindowsShellService");
XPCOMUtils.defineLazyGetter(this, "_prefs", function() {
return Services.prefs.getBranch(PREF_TASKBAR_BRANCH)
.QueryInterface(Ci.nsIPrefBranch2);
@ -103,6 +107,16 @@ let WinTaskbarJumpList = {
if (!this._initTaskbar())
return;
// Win shell shortcut maintenance. If we've gone through an update,
// this will update any pinned taskbar shortcuts. Not specific to
// jump lists, but this was a convienent place to call it.
try {
// dev builds may not have helper.exe, ignore failures.
this._shortcutMaintenance();
}
catch (ex) {
}
// Store our task list config data
this._tasks = gTasks;
@ -130,6 +144,10 @@ let WinTaskbarJumpList = {
this._free();
},
_shortcutMaintenance: function WTBJL__maintenace() {
_winShellService.shortcutMaintenance();
},
/**
* List building
*/

Просмотреть файл

@ -7,7 +7,9 @@
# Note - Thunderbird does not set a Vendor in application.ini!
!define AppName "Thunderbird"
!define AppVersion "@MOZ_APP_VERSION@"
!define AppUserModelID "${AppName}.${AppVersion}"
# The app vendor is blank, and the way app model IDs are formed is with
# vendor.name.version.
!define AppUserModelID ".${AppName}.${AppVersion}"
!define GREVersion @MOZILLA_VERSION@
!define AB_CD "@AB_CD@"

Просмотреть файл

@ -114,6 +114,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
!insertmacro RegCleanMain
!insertmacro RegCleanUninstall
!insertmacro SetBrandNameVars
!insertmacro UpdateShortcutAppModelIDs
!insertmacro UnloadUAC
!insertmacro WriteRegStr2
!insertmacro WriteRegDWORD2
@ -401,6 +402,29 @@ Section "-Application" APP_IDX
${LogQuickLaunchShortcut} "${BrandFullName}.lnk"
${LogDesktopShortcut} "${BrandFullName}.lnk"
; Best effort to update the Win7 taskbar and start menu shortcut app model
; id's. The possible contexts are current user / system and the user that
; elevated the installer.
Call FixShortcutAppModelIDs
; If the current context is all also perform Win7 taskbar and start menu link
; maintenance for the current user context.
${If} $TmpVal == "HKLM"
SetShellVarContext current ; Set SHCTX to HKCU
Call FixShortcutAppModelIDs
SetShellVarContext all ; Set SHCTX to HKLM
${EndIf}
; If running elevated also perform Win7 taskbar and start menu link
; maintenance for the unelevated user context in case that is different than
; the current user.
ClearErrors
${GetParameters} $0
${GetOptions} "$0" "/UAC:" $0
${Unless} ${Errors}
GetFunctionAddress $0 FixShortcutAppModelIDs
UAC::ExecCodeSegment $0
${EndIf}
; UAC only allows elevating to an Admin account so there is no need to add
; the Start Menu or Desktop shortcuts from the original unelevated process
; since this will either add it for the user if unelevated or All Users if
@ -465,6 +489,9 @@ Section "-InstallEndCleanup"
${EndIf}
${EndUnless}
; Win7 taskbar and start menu link maintenance
Call FixShortcutAppModelIDs
; Refresh desktop icons
System::Call "shell32::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)"

Просмотреть файл

@ -45,6 +45,8 @@
${RegCleanMain} "Software\Mozilla"
${RegCleanUninstall}
${UpdateProtocolHandlers}
; Win7 taskbar and start menu link maintenance
Call FixShortcutAppModelIDs
; Upgrade the copies of the MAPI DLL's
${UpgradeMapiDLLs}
@ -70,6 +72,9 @@
${RegCleanUninstall}
${UpdateProtocolHandlers}
; Win7 taskbar and start menu link maintenance
Call FixShortcutAppModelIDs
; Only update the Clients\Mail registry key values if they don't exist or
; this installation is the same as the one set in those keys.
ReadRegStr $0 HKLM "Software\Clients\Mail\${ClientsRegName}\DefaultIcon" ""
@ -729,6 +734,11 @@
!macroend
!define PushFilesToCheck "!insertmacro PushFilesToCheck"
; Helper for updating the shortcut application model IDs.
Function FixShortcutAppModelIDs
${UpdateShortcutAppModelIDs} "$INSTDIR\${FileMainEXE}" "${AppUserModelID}" $0
FunctionEnd
; The !ifdef NO_LOG prevents warnings when compiling the installer.nsi due to
; this function only being used by the uninstaller.nsi.
!ifdef NO_LOG