--- a/mail/base/content/msgMail3PaneWindow.js
+++ b/mail/base/content/msgMail3PaneWindow.js
@@ -797,39 +797,42 @@ function LoadPostAccountWizard()
gStartFolderUri = null;
}
else
gStartFolderUri = (window.arguments.length > 0) ? window.arguments[0] : null;
gStartMsgKey = (window.arguments.length > 1) ? window.arguments[1]: nsMsgKey_None;
gSearchEmailAddress = (window.arguments.length > 2) ? window.arguments[2] : null;
}
+ function showDefaultClientDialog() {
#ifdef HAVE_SHELL_SERVICE
- var nsIShellService = Components.interfaces.nsIShellService;
- var shellService;
- var defaultAccount;
- try {
- shellService = Components.classes["@mozilla.org/mail/shell-service;1"].getService(nsIShellService);
- defaultAccount = accountManager.defaultAccount;
- } catch (ex) {}
+ var nsIShellService = Components.interfaces.nsIShellService;
+ var shellService;
+ var defaultAccount;
+ try {
+ shellService = Components.classes["@mozilla.org/mail/shell-service;1"].getService(nsIShellService);
+ defaultAccount = accountManager.defaultAccount;
+ } catch (ex) {}
- function showDefaultClientDialog() {
- window.openDialog("chrome://messenger/content/defaultClientDialog.xul",
- "DefaultClient", "modal,centerscreen,chrome,resizable=no");
+ // Show the default client dialog only if we have at least one account,
+ // we should check for the default client, and we aren't already the default
+ // for mail.
+ // Needs to be shown outside the he normal load sequence so it doesn't appear
+ // before any other displays, in the wrong place of the screen.
+ if (shellService && defaultAccount && shellService.shouldCheckDefaultClient
+ && !shellService.isDefaultClient(true, nsIShellService.MAIL))
+ window.openDialog("chrome://messenger/content/defaultClientDialog.xul",
+ "DefaultClient", "modal,centerscreen,chrome,resizable=no");
+#endif
+
+ // All core modal dialogs are done, the user can now interact with the 3-pane window
+ NotifyObservers(window, "mail-startup-done", null);
}
- // Show the default client dialog only if we have at least one account,
- // we should check for the default client, and we aren't already the default
- // for mail.
- // Needs to be shown outside the he normal load sequence so it doesn't appear
- // before any other displays, in the wrong place of the screen.
- if (shellService && defaultAccount && shellService.shouldCheckDefaultClient
- && !shellService.isDefaultClient(true, nsIShellService.MAIL))
- setTimeout(showDefaultClientDialog, 0);
-#endif
+ setTimeout(showDefaultClientDialog, 0);
// FIX ME - later we will be able to use onload from the overlay
OnLoadMsgHeaderPane();
gHaveLoadedMessage = false;
gNotifyDefaultInboxLoadedOnStartup = true;
--- a/mail/components/Makefile.in
+++ b/mail/components/Makefile.in
@@ -48,18 +48,23 @@ ifneq (,$(filter windows gtk2 mac cocoa,
DIRS += shell
endif
ifdef MOZ_SAFE_BROWSING
DIRS += phishing
endif
# Mac and Windows have search integration components
-ifneq (,$(filter windows cocoa mac, $(MOZ_WIDGET_TOOLKIT)))
+ifneq (,$(filter cocoa mac, $(MOZ_WIDGET_TOOLKIT)))
DIRS += search
endif
+ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+ifndef MOZ_DISABLE_VISTA_SDK_REQUIREMENTS
+DIRS += search
+endif
+endif
DIRS += build
EXTRA_PP_COMPONENTS = nsMailDefaultHandler.js
include $(topsrcdir)/config/rules.mk
--- a/mail/components/build/Makefile.in
+++ b/mail/components/build/Makefile.in
@@ -64,36 +64,58 @@ REQUIRES = \
libreg \
intl \
pref \
msgbase \
import \
shellservice \
$(NULL)
+ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+ifndef MOZ_DISABLE_VISTA_SDK_REQUIREMENTS
+REQUIRES += \
+ mailwinsearch \
+ $(NULL)
+endif
+endif
+
CPPSRCS = nsModule.cpp \
$(NULL)
ifeq ($(OS_ARCH),WINNT)
OS_LIBS += $(call EXPAND_LIBNAME,ole32 shell32)
endif
LOCAL_INCLUDES = \
-I$(srcdir)/../migration/src \
-I$(srcdir)/../shell \
$(NULL)
+ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+ifndef MOZ_DISABLE_VISTA_SDK_REQUIREMENTS
+LOCAL_INCLUDES += \
+ -I$(srcdir)/../search \
+ $(NULL)
+endif
+endif
+
SHARED_LIBRARY_LIBS = \
../migration/src/$(LIB_PREFIX)profilemigration_s.$(LIB_SUFFIX) \
$(NULL)
ifneq (,$(filter windows mac cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
SHARED_LIBRARY_LIBS += ../shell/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX)
endif
+ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+ifndef MOZ_DISABLE_VISTA_SDK_REQUIREMENTS
+SHARED_LIBRARY_LIBS += ../search/$(LIB_PREFIX)winsearch_s.$(LIB_SUFFIX)
+endif
+endif
+
ifdef MOZILLA_INTERNAL_API
EXTRA_DSO_LDOPTS += \
$(LIBXUL_DIST)/../modules/libreg/src/$(LIB_PREFIX)mozreg_s.$(LIB_SUFFIX) \
$(MOZ_COMPONENT_LIBS) \
$(MOZ_UNICHARUTIL_LIBS) \
$(NULL)
else
EXTRA_DSO_LDOPTS += \
--- a/mail/components/build/nsModule.cpp
+++ b/mail/components/build/nsModule.cpp
@@ -73,16 +73,21 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEudoraP
#include "nsMailGNOMEIntegration.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMailGNOMEIntegration, Init)
#endif
#ifdef XP_MACOSX
#include "nsMailMacIntegration.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMailMacIntegration)
#endif
+#if defined(XP_WIN32) && !defined(MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
+#include "nsMailWinSearchHelper.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMailWinSearchHelper, Init)
+#endif
+
static const nsModuleComponentInfo components[] = {
{ "Profile Importer",
NS_THUNDERBIRD_PROFILEIMPORT_CID,
NS_PROFILEMIGRATOR_CONTRACTID,
nsProfileMigratorConstructor },
{ "Seamonkey Profile Migrator",
NS_SEAMONKEYPROFILEMIGRATOR_CID,
NS_MAILPROFILEMIGRATOR_CONTRACTID_PREFIX "seamonkey",
@@ -122,11 +127,17 @@ static const nsModuleComponentInfo compo
nsMailGNOMEIntegrationConstructor },
#endif
#ifdef XP_MACOSX
{ "Mail Mac Integration",
NS_MAILMACINTEGRATION_CID,
"@mozilla.org/mail/shell-service;1",
nsMailMacIntegrationConstructor },
#endif
+#if defined(XP_WIN32) && !defined(MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
+ { "Mail Windows Search Integration Helper",
+ NS_MAILWINSEARCHHELPER_CID,
+ "@mozilla.org/mail/windows-search-helper;1",
+ nsMailWinSearchHelperConstructor },
+#endif
};
NS_IMPL_NSGETMODULE(nsMailCompsModule, components)
--- a/mail/components/search/Makefile.in
+++ b/mail/components/search/Makefile.in
@@ -41,25 +41,53 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
ifneq (,$(filter cocoa mac, $(MOZ_WIDGET_TOOLKIT)))
DIRS += mdimporter
endif
+ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+DIRS += wsenable
+endif
+
#currently, we only build this dir on the mac, but if it gets built on other platforms,
#make sure we still only build spotlight integration on the mac.
ifneq (,$(filter cocoa mac, $(MOZ_WIDGET_TOOLKIT)))
EXTRA_PP_COMPONENTS = \
nsSpotlightIntegration.js \
$(NULL)
endif
# If on Windows, build Windows Search integration
ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
+MODULE = mailwinsearch
+LIBRARY_NAME = winsearch_s
+MODULE_NAME = nsMailWinSearchHelperModule
+ifdef BUILD_STATIC_LIBS
+MOZILLA_INTERNAL_API = 1
+else
+ifneq ($(MOZ_WIDGET_TOOLKIT), gtk2)
+MOZILLA_INTERNAL_API = 1
+endif
+endif
+
+REQUIRES = \
+ xpcom \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ nsMailWinSearchHelper.cpp \
+ $(NULL)
+
+DIRS += public
+
# Windows Search component
EXTRA_PP_COMPONENTS = \
nsWinSearchIntegration.js \
$(NULL)
+
+FORCE_STATIC_LIB = 1
endif
include $(topsrcdir)/config/rules.mk
--- a/mail/components/search/content/searchCommon.js
+++ b/mail/components/search/content/searchCommon.js
@@ -55,32 +55,46 @@ const Ci = Components.interfaces;
var gCurrentFolderToIndex;
var gLastFolderIndexedUri = ""; // this is stored in a pref
var gHeaderEnumerator;
var gMsgHdrsToIndex;
var gMessenger;
var gAlarm;
var gBackgroundIndexingDone;
var gPrefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService).getBranch(null);
+var gEnabled;
/*
* Init function -- this should be called from the component's init function
*/
-function InitSupportIntegration()
+function InitSupportIntegration(enabled)
{
+ SIDump("Search integration running in " + (enabled ? "active" : "backoff") + " mode\n");
+ gEnabled = enabled;
+
gMessenger = Cc["@mozilla.org/messenger;1"].createInstance().QueryInterface(Ci.nsIMessenger);
var notificationService = Cc["@mozilla.org/messenger/msgnotificationservice;1"]
.getService(Ci.nsIMsgFolderNotificationService);
- notificationService.addListener(gFolderListener, notificationService.all);
- var ObserverService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
- ObserverService.addObserver(MsgMsgDisplayedObserver, "MsgMsgDisplayed", false);
- gMsgHdrsToIndex = new Array();
- restartTimer(60);
+ // We want to observe moves, deletes and renames in case we're disabled
+ // If we don't, we'll have no idea the support files exist later
+ if (enabled)
+ {
+ notificationService.addListener(gFolderListener, notificationService.all);
+ var ObserverService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+ ObserverService.addObserver(MsgMsgDisplayedObserver, "MsgMsgDisplayed", false);
+ gMsgHdrsToIndex = new Array();
+
+ restartTimer(60);
+ }
+ else
+ notificationService.addListener(gFolderListener, notificationService.msgsMoveCopyCompleted |
+ notificationService.msgsDeleted |
+ notificationService.allFolderNotifications);
}
/*
* These functions are to index already existing messages
*/
function FindNextFolderToIndex()
{
accountManager = Cc["@mozilla.org/messenger/account-manager;1"].getService(Ci.nsIMsgAccountManager);
@@ -224,17 +238,18 @@ var gFolderListener = {
if (!file.exists())
QueueMessageToGetIndexed(aMsg);
},
msgsDeleted: function(aMsgs)
{
SIDump("in msgsDeleted\n");
// mail getting deleted, we're not idle, so restart timer.
- restartTimer(60);
+ if (gEnabled)
+ restartTimer(60);
var count = aMsgs.length;
for (var i = 0; i < count; i++)
{
var file = GetSupportFileForMsgHdr(aMsgs.queryElementAt(i, Ci.nsIMsgDBHdr));
if (file.exists())
file.remove(false);
}
},
@@ -257,49 +272,53 @@ var gFolderListener = {
{
// create the directory, if it doesn't exist
destFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0644);
}
catch(ex) {SIDump(ex);}
}
SIDump ("dst file path = " + destFile.path + "\n");
SIDump ("src file path = " + srcFile.path + "\n");
+ // We're not going to copy in case we're not in active mode
if (destFile.exists())
if (aMove)
srcFile.moveTo(destFile, "");
- else
+ else if (gEnabled)
srcFile.copyTo(destFile, "");
}
}
- restartTimer(30);
+ if (gEnabled)
+ restartTimer(30);
SIDump("moveCopyCompleted move = " + aMove + "\n");
},
folderDeleted: function(aFolder)
{
SIDump("in folderDeleted, folder name = " + aFolder.prettiestName + "\n");
var srcFile = aFolder.filePath;
srcFile.leafName = srcFile.leafName + ".mozmsgs";
- srcFile.remove(true);
+ if (srcFile.exists())
+ srcFile.remove(true);
},
folderMoveCopyCompleted: function(aMove, aSrcFolder, aDestFolder)
{
SIDump("in folderMoveCopyCompleted, aMove = " + aMove + "\n");
var srcFile = aSrcFolder.filePath;
var destFile = aDestFolder.filePath;
srcFile.leafName = srcFile.leafName + ".mozmsgs";
destFile.leafName += ".sbd";
SIDump("src file path = " + srcFile.path + "\n");
SIDump("dst file path = " + destFile.path + "\n");
if (srcFile.exists())
{
+ // We're not going to copy if we aren't in active mode
if (aMove)
srcFile.moveTo(destFile, "");
- else
+ else if (gEnabled)
srcFile.copyTo(destFile, "");
}
},
folderRenamed: function(aOrigFolder, aNewFolder)
{
SIDump("in folderRenamed, aOrigFolder = "+aOrigFolder.prettiestName+", aNewFolder = "+aNewFolder.prettiestName+"\n");
var srcFile = aOrigFolder.filePath;
new file mode 100644
--- /dev/null
+++ b/mail/components/search/content/searchIntegrationDialog.xul
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+# -*- Mode: xml; indent-tabs-mode: nil; -*-
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is the Thunderbird Default Client Dialog
+#
+# The Initial Developer of the Original Code is
+# Scott MacGregor.
+# Portions created by the Initial Developer are Copyright (C) 2006
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Scott MacGregor <mscott@mozilla.org
+# Siddharth Agarwal <sid1337@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 *****
+
+<?xml-stylesheet href="chrome://global/skin/"?>
+
+<!DOCTYPE window [
+ <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+ %brandDTD;
+#ifdef XP_WIN
+ <!ENTITY % searchIntegrationDTD SYSTEM "chrome://messenger/locale/search/searchIntegrationDialogWin.dtd" >
+ %searchIntegrationDTD;
+#endif
+]>
+
+
+<dialog xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ id="searchIntegrationDialog"
+ buttons="accept,cancel"
+ ondialogaccept="window.arguments[0].callback(true); return true"
+ ondialogcancel="window.arguments[0].callback(false); return true"
+ title="&searchIntegration.title;"
+ buttonlabelaccept="&searchIntegration.accept;"
+ buttonlabelcancel="&searchIntegration.cancel;">
+
+ <description>
+ &searchIntegration.description;
+ </description>
+
+</dialog>
new file mode 100644
--- /dev/null
+++ b/mail/components/search/jar.mn
@@ -0,0 +1,2 @@
+messenger.jar:
+* content/messenger/search/searchIntegrationDialog.xul (content/searchIntegrationDialog.xul)
new file mode 100644
--- /dev/null
+++ b/mail/components/search/nsMailWinSearchHelper.cpp
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; 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 Windows Search integration.
+ *
+ * The Initial Developer of the Original Code is
+ * Siddharth Agarwal <sid1337@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMailWinSearchHelper.h"
+#include "nsDirectoryServiceUtils.h"
+#include "nsAutoPtr.h"
+#include "nsMemory.h"
+#include "nsStringGlue.h"
+#include "nsISimpleEnumerator.h"
+#include <SearchAPI.h>
+#include <winsvc.h>
+#include <ShellAPI.h>
+
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+#define _WIN32_WINNT 0x0600
+#include <shlobj.h>
+
+static const CLSID CLSID_CSearchManager = {0x7d096c5f, 0xac08, 0x4f1f, {0xbe, 0xb7, 0x5c, 0x22, 0xc5, 0x17, 0xce, 0x39}};
+static const IID IID_ISearchManager = {0xab310581, 0xac80, 0x11d1, {0x8d, 0xf3, 0x00, 0xc0, 0x4f, 0xb6, 0xef, 0x69}};
+
+static const char* const sFoldersToIndex[] = {"Mail", "ImapMail", "News"};
+
+// APP_REG_NAME_MAIL should be kept in synch with AppRegNameMail
+// in the installer file: defines.nsi.in
+#define APP_REG_NAME_MAIL L"Thunderbird"
+
+nsMailWinSearchHelper::nsMailWinSearchHelper()
+{
+}
+
+nsresult nsMailWinSearchHelper::Init()
+{
+ CoInitialize(NULL);
+ return NS_GetSpecialDirectory("ProfD", getter_AddRefs(mProfD));
+}
+
+nsMailWinSearchHelper::~nsMailWinSearchHelper()
+{
+ CoUninitialize();
+}
+
+NS_IMPL_ISUPPORTS1(nsMailWinSearchHelper, nsIMailWinSearchHelper)
+
+
+NS_IMETHODIMP nsMailWinSearchHelper::GetFoldersInCrawlScope(PRBool* aResult)
+{
+ *aResult = PR_FALSE;
+ NS_ENSURE_ARG_POINTER(mProfD);
+
+ // If the service isn't present or running, we shouldn't proceed.
+ PRBool serviceRunning;
+ nsresult rv = GetServiceRunning(&serviceRunning);
+ if (!serviceRunning || NS_FAILED(rv))
+ return rv;
+
+ // We need to do this every time so that we have the latest data
+ nsRefPtr<ISearchManager> searchManager;
+ HRESULT hr = CoCreateInstance(CLSID_CSearchManager, NULL, CLSCTX_ALL, IID_ISearchManager, getter_AddRefs(searchManager));
+ if (FAILED(hr))
+ return NS_ERROR_FAILURE;
+
+ nsRefPtr<ISearchCatalogManager> catalogManager;
+ hr = searchManager->GetCatalog(L"SystemIndex", getter_AddRefs(catalogManager));
+ if (FAILED(hr))
+ return NS_ERROR_FAILURE;
+
+ nsRefPtr<ISearchCrawlScopeManager> crawlScopeManager;
+ hr = catalogManager->GetCrawlScopeManager(getter_AddRefs(crawlScopeManager));
+ if (FAILED(hr))
+ return NS_ERROR_FAILURE;
+
+ // We need to create appropriate URLs to check with the crawl scope manager.
+ for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sFoldersToIndex); i++)
+ {
+ nsCOMPtr<nsIFile> subdir;
+ rv = mProfD->Clone(getter_AddRefs(subdir));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsDependentCString relativeStr(sFoldersToIndex[i]);
+ rv = subdir->AppendNative(relativeStr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsString subdirPath;
+ rv = subdir->GetPath(subdirPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Form a URL as required by the crawl scope manager
+ nsString subdirURL(NS_LITERAL_STRING("file:///"));
+ subdirURL.Append(subdirPath);
+ subdirURL.Append(NS_LITERAL_STRING("\\"));
+
+ BOOL included;
+ if (FAILED(crawlScopeManager->IncludedInCrawlScope(subdirURL.get(), &included)))
+ return NS_ERROR_FAILURE;
+
+ // If even one of the folders isn't there, we return false
+ if (!included)
+ return NS_OK;
+ }
+ *aResult = PR_TRUE;
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailWinSearchHelper::GetServiceRunning(PRBool* aResult)
+{
+ *aResult = PR_FALSE;
+ SC_HANDLE hSCManager = OpenSCManager(nsnull, SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_STATUS);
+ if (!hSCManager)
+ return NS_ERROR_FAILURE;
+
+ SC_HANDLE hService = OpenService(hSCManager, "wsearch", SERVICE_QUERY_STATUS);
+ CloseServiceHandle(hSCManager);
+ if (!hService)
+ // The service isn't present. Never mind.
+ return NS_ERROR_NOT_AVAILABLE;
+
+ SERVICE_STATUS status;
+ if (!QueryServiceStatus(hService, &status))
+ {
+ CloseServiceHandle(hService);
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = (status.dwCurrentState == SERVICE_RUNNING);
+ CloseServiceHandle(hService);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailWinSearchHelper::SetFANCIBit(nsIFile* aFile, PRBool aBit, PRBool aRecurse)
+{
+ NS_ENSURE_ARG_POINTER(aFile);
+
+ PRBool exists;
+ nsresult rv = aFile->Exists(&exists);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (!exists)
+ return NS_ERROR_FILE_NOT_FOUND;
+
+ nsString filePath;
+ rv = aFile->GetPath(filePath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ LPCWSTR pathStr = filePath.get();
+
+ // We should set the file attribute only if it isn't already set.
+ DWORD dwAttrs = GetFileAttributesW(pathStr);
+ if (dwAttrs == INVALID_FILE_ATTRIBUTES)
+ return NS_ERROR_FAILURE;
+
+ if (aBit)
+ {
+ if (!(dwAttrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED))
+ SetFileAttributesW(pathStr, dwAttrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+ }
+ else
+ {
+ if (dwAttrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
+ SetFileAttributesW(pathStr, dwAttrs & ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED);
+ }
+
+ // We should only try to recurse if it's a directory
+ PRBool isDirectory;
+ rv = aFile->IsDirectory(&isDirectory);
+ NS_ENSURE_SUCCESS(rv, rv);
+ if (aRecurse && isDirectory)
+ {
+ nsCOMPtr<nsISimpleEnumerator> children;
+ rv = aFile->GetDirectoryEntries(getter_AddRefs(children));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool hasMore;
+ while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(children->HasMoreElements(&hasMore)) && hasMore)
+ {
+ nsCOMPtr<nsIFile> childFile;
+ rv = children->GetNext(getter_AddRefs(childFile));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = SetFANCIBit(childFile, aBit, aRecurse);
+ }
+ }
+ return rv;
+}
+
+NS_IMETHODIMP nsMailWinSearchHelper::GetIsFileAssociationSet(PRBool *aResult)
+{
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = PR_FALSE;
+
+ // We'll use the Vista method here
+ nsRefPtr<IApplicationAssociationRegistration> pAAR;
+ HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
+ NULL,
+ CLSCTX_INPROC,
+ IID_IApplicationAssociationRegistration,
+ getter_AddRefs(pAAR));
+
+ if (SUCCEEDED(hr))
+ pAAR->QueryAppIsDefault(L".wdseml", AT_FILEEXTENSION, AL_EFFECTIVE, APP_REG_NAME_MAIL, aResult);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsMailWinSearchHelper::SetFileAssociation()
+{
+ nsRefPtr<IApplicationAssociationRegistration> pAAR;
+ HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
+ NULL,
+ CLSCTX_INPROC,
+ IID_IApplicationAssociationRegistration,
+ getter_AddRefs(pAAR));
+ if (SUCCEEDED(hr))
+ hr = pAAR->SetAppAsDefault(APP_REG_NAME_MAIL, L".wdseml", AT_FILEEXTENSION);
+
+ return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP nsMailWinSearchHelper::RunSetup(PRBool aEnable)
+{
+ nsresult rv;
+ if (!mCurProcD)
+ {
+ rv = NS_GetSpecialDirectory("CurProcD", getter_AddRefs(mCurProcD));
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = mCurProcD->Append(NS_LITERAL_STRING("WSEnable.exe"));
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ nsAutoString filePath;
+ rv = mCurProcD->GetPath(filePath);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // The parameters are of the format "1 <path>" for enabling and "0 <path>" for disabling
+ nsAutoString params(aEnable ? NS_LITERAL_STRING("1 \"") : NS_LITERAL_STRING("0 \""));
+ nsAutoString profDPath;
+ rv = mProfD->GetPath(profDPath);
+ NS_ENSURE_SUCCESS(rv, rv);
+ params.Append(profDPath);
+ params.Append(NS_LITERAL_STRING("\""));
+
+ // We need an hWnd to cause UAC to pop up immediately
+ // If GetForegroundWindow returns NULL, then the UAC prompt will still appear,
+ // but minimized.
+ HWND hWnd = GetForegroundWindow();
+
+ SHELLEXECUTEINFOW executeInfo = {0};
+
+ executeInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
+ executeInfo.hwnd = hWnd;
+ executeInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+ executeInfo.lpDirectory = NULL;
+ executeInfo.lpFile = filePath.get();
+ executeInfo.lpParameters = params.get();
+ executeInfo.nShow = SW_SHOWNORMAL;
+
+ DWORD dwRet;
+
+ if (ShellExecuteExW(&executeInfo))
+ {
+ // We want to block until the program exits
+ DWORD dwSignaled = WaitForSingleObject(executeInfo.hProcess, INFINITE);
+ if (dwSignaled == WAIT_OBJECT_0)
+ if (!GetExitCodeProcess(executeInfo.hProcess, &dwRet))
+ dwRet = GetLastError();
+ }
+ else
+ return NS_ERROR_ABORT;
+
+ return SUCCEEDED(HRESULT_FROM_WIN32(dwRet)) ? NS_OK : NS_ERROR_FAILURE;
+}
new file mode 100644
--- /dev/null
+++ b/mail/components/search/nsMailWinSearchHelper.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; 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 Windows Search integration.
+ *
+ * The Initial Developer of the Original Code is
+ * Siddharth Agarwal <sid1337@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsMailWinSearchHelper_h_
+#define nsMailWinSearchHelper_h_
+
+#include "nsIMailWinSearchHelper.h"
+#include "nsIFile.h"
+
+#define NS_MAILWINSEARCHHELPER_CID \
+{0x5dd31c99, 0x8c7, 0x4a3b, {0xae, 0xb3, 0xd2, 0xe6, 0x6, 0x65, 0xa3, 0x1a}}
+
+class nsMailWinSearchHelper : public nsIMailWinSearchHelper
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIMAILWINSEARCHHELPER
+
+ NS_HIDDEN_(nsresult) Init();
+ nsMailWinSearchHelper();
+
+private:
+ ~nsMailWinSearchHelper();
+ nsCOMPtr<nsIFile> mProfD;
+ nsCOMPtr<nsIFile> mCurProcD;
+};
+
+#endif
--- a/mail/components/search/nsSpotlightIntegration.js
+++ b/mail/components/search/nsSpotlightIntegration.js
@@ -54,21 +54,19 @@ Components.utils.import("resource://gre/
function InitSpotlightIntegration()
{
var enabled;
try {
enabled = gPrefBranch.getBoolPref(gPrefBase + ".enable");
gLastFolderIndexedUri = gPrefBranch.getCharPref(gPrefBase + ".lastFolderIndexedUri");
} catch (ex) {}
- if (!enabled)
- return;
-
- SIDump("initializing spotlight integration\n");
- InitSupportIntegration();
+ if (enabled)
+ SIDump("initializing spotlight integration\n");
+ InitSupportIntegration(enabled);
}
function xmlEscapeString(s)
{
s = s.replace(/&/g, "&");
s = s.replace(/>/g, ">");
s = s.replace(/</g, "<");
return s;
--- a/mail/components/search/nsWinSearchIntegration.js
+++ b/mail/components/search/nsWinSearchIntegration.js
@@ -46,31 +46,155 @@ const CRLF="\r\n";
const gHdrIndexedProperty = "wds_indexed";
// The file extension that is used for support files of this component
const gFileExt = ".wdseml";
// The pref base
const gPrefBase = "mail.winsearch";
+var gWinSearchHelper;
+
+var gFoldersInCrawlScope;
+
+var gRegKeysPresent;
+
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function InitWinSearchIntegration()
{
+ // We're currently only enabled on Vista and above
+ var sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
+ var windowsVersion = sysInfo.getProperty("version");
+ if (parseFloat(windowsVersion) < 6)
+ {
+ SIDump("Windows version " + windowsVersion + " < 6.0\n");
+ return;
+ }
+
+ // enabled === undefined means that the first run hasn't occurred yet (pref isn't present).
+ // false or true means that the first run has occurred, and the user has selected
+ // the corresponding decision.
var enabled;
try {
enabled = gPrefBranch.getBoolPref(gPrefBase + ".enable");
gLastFolderIndexedUri = gPrefBranch.getCharPref(gPrefBase + ".lastFolderIndexedUri");
} catch (ex) {}
- if (!enabled)
+ gWinSearchHelper = Cc["@mozilla.org/mail/windows-search-helper;1"].getService(Ci.nsIMailWinSearchHelper);
+ var serviceRunning = false;
+ try
+ {
+ serviceRunning = gWinSearchHelper.serviceRunning;
+ }
+ catch (e) {}
+ // If the service isn't running, then we should stay in backoff mode
+ if (!serviceRunning)
+ {
+ SIDump("Windows Search service not running\n");
+ InitSupportIntegration(false);
return;
+ }
+
+ gFoldersInCrawlScope = gWinSearchHelper.foldersInCrawlScope;
+ gRegKeysPresent = CheckRegistryKeys();
+
+ if (enabled === undefined)
+ // First run has to be handled after the main mail window is open
+ return true;
+
+ if (enabled)
+ SIDump("Initializing Windows Search integration\n");
+ InitSupportIntegration(enabled);
+}
+
+// Handles first run, once the main mail window has popped up.
+function WinSearchFirstRun(window)
+{
+ // If any of the two are not present, we need to elevate.
+ var needsElevation = !gFoldersInCrawlScope || !gRegKeysPresent;
+ var params = {in: {showUAC: needsElevation}};
+ var scope = this;
+
+ params.callback = function(enable)
+ {
+ CheckRegistryKeys();
+ if (enable && needsElevation)
+ {
+ try { scope.gWinSearchHelper.runSetup(true); }
+ catch (e) { enable = false; }
+ }
+ if (enable)
+ {
+ if (!scope.gWinSearchHelper.isFileAssociationSet)
+ scope.gWinSearchHelper.setFileAssociation();
+ }
+ scope.gPrefBranch.setBoolPref(gPrefBase + ".enable", enable);
+ scope.InitSupportIntegration(enable);
+ }
+
+ window.openDialog("chrome://messenger/content/search/searchIntegrationDialog.xul", "",
+ "chrome, dialog, resizable=no, centerscreen", params).focus();
+}
- SIDump("Initializing Windows Search integration\n");
- InitSupportIntegration();
+const gRegKeys =
+[
+ // This is the property handler
+ {
+ root: Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+ key: "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PropertySystem\\PropertyHandlers\\.wdseml",
+ name: "",
+ value: "{5FA29220-36A1-40f9-89C6-F4B384B7642E}"
+ },
+ // These two are the association with the MIME IFilter
+ {
+ root: Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT,
+ key: ".wdseml",
+ name: "Content Type",
+ value: "message/rfc822"
+ },
+ {
+ root: Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT,
+ key: ".wdseml\\PersistentHandler",
+ name: "",
+ value: "{5645c8c4-e277-11cf-8fda-00aa00a14f93}"
+ },
+ // This is the association with the Windows mail preview handler
+ {
+ root: Ci.nsIWindowsRegKey.ROOT_KEY_CLASSES_ROOT,
+ key: ".wdseml\\shellex\\{8895B1C6-B41F-4C1C-A562-0D564250836F}",
+ name: "",
+ value: "{b9815375-5d7f-4ce2-9245-c9d4da436930}"
+ },
+ // This is the association made to display results under email
+ {
+ root: Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
+ key: "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\KindMap",
+ name: ".wdseml",
+ value: "email;communication"
+ }
+];
+
+// Check whether the required registry keys exist
+function CheckRegistryKeys()
+{
+ for (var i = 0; i < gRegKeys.length; i++)
+ {
+ var regKey = Cc["@mozilla.org/windows-registry-key;1"].createInstance(Ci.nsIWindowsRegKey);
+ try {
+ regKey.open(gRegKeys[i].root, gRegKeys[i].key, regKey.ACCESS_READ);
+ }
+ catch (e) { return false; }
+ var valuePresent = regKey.hasValue(gRegKeys[i].name) &&
+ (regKey.readStringValue(gRegKeys[i].name) == gRegKeys[i].value);
+ regKey.close();
+ if (!valuePresent)
+ return false;
+ }
+ return true;
}
// The stream listener to read messages
var gStreamListener = {
_buffer: "",
outputFile: null,
outputStream: null,
unicodeConverter: null,
@@ -202,26 +326,36 @@ WinSearchIntegration.prototype = {
category: "app-startup",
service: true
}],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupports]),
observe : function(aSubject, aTopic, aData)
{
+ var obsSvc = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
switch(aTopic)
{
case "app-startup":
- var obsSvc = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
obsSvc.addObserver(this, "profile-after-change", false);
- break;
+ break;
case "profile-after-change":
- try { InitWinSearchIntegration(); }
+ try
+ {
+ if (InitWinSearchIntegration())
+ obsSvc.addObserver(this, "mail-startup-done", false);
+ }
catch(err) { SIDump("Could not initialize winsearch component"); }
- break;
+ break;
+ case "mail-startup-done":
+ aSubject.QueryInterface(Ci.nsIDOMWindowInternal);
+ obsSvc.removeObserver(this, "mail-startup-done");
+ try { WinSearchFirstRun(aSubject); }
+ catch(err) { SIDump("First run unsuccessful\n"); }
+ break;
default:
throw Components.Exception("Unknown topic: " + aTopic);
}
}
};
var components = [WinSearchIntegration];
function NSGetModule(aCompMgr, aFileSpec)
{
new file mode 100644
--- /dev/null
+++ b/mail/components/search/public/Makefile.in
@@ -0,0 +1,49 @@
+# ***** 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 Windows Search integration.
+#
+# The Initial Developer of the Original Code is
+# Siddharth Agarwal <sid1337@gmail.com>.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = mailwinsearch
+XPIDL_MODULE = mailwinsearch
+
+XPIDLSRCS = nsIMailWinSearchHelper.idl
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/mail/components/search/public/nsIMailWinSearchHelper.idl
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; 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 Windows Search integration.
+ *
+ * The Initial Developer of the Original Code is
+ * Siddharth Agarwal <sid1337@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+
+#include "nsISupports.idl"
+
+interface nsIFile;
+
+[scriptable, uuid(a65307b3-64f8-49fc-96a7-2cfc7d1f18ee)]
+interface nsIMailWinSearchHelper : nsISupports
+{
+ /**
+ * Whether the Windows Search service is installed and running.
+ *
+ * @exception NS_ERROR_NOT_AVAILABLE if the Windows Search service is
+ * not installed
+ */
+ readonly attribute boolean serviceRunning;
+
+ /**
+ * Whether the Mail, ImapMail, and News folders are in the crawl scope.
+ *
+ * @exception NS_ERROR_NOT_AVAILABLE if the Windows Search service is not
+ * installed or running
+ */
+ readonly attribute boolean foldersInCrawlScope;
+
+ /**
+ * Sets the File Attribute Not Content Indexed bit. For proper operation
+ * of the indexer, this bit must be set to 0/false.
+ *
+ * @param aFile the file or directory for which this bit is supposed to be set
+ * @param aBit false if the content is to be indexed, true if not
+ * @param aRecurse whether this bit is to be set recursively for all subdirectories
+ * and files inside a directory
+ */
+ void setFANCIBit(in nsIFile aFile, in boolean aBit, in boolean aRecurse);
+
+ /**
+ * Returns whether the .wdseml file association has been set to Thunderbird or not.
+ */
+ readonly attribute boolean isFileAssociationSet;
+
+ /**
+ * Sets the .wdseml file association.
+ */
+ void setFileAssociation();
+
+ /**
+ * Runs the setup application using ShellExecute, passing the profile directory as
+ * a parameter.
+ *
+ * @param aEnable true to enable, false to disable
+ */
+ void runSetup(in boolean aEnable);
+};
new file mode 100644
--- /dev/null
+++ b/mail/components/search/wsenable/Makefile.in
@@ -0,0 +1,52 @@
+# ***** 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 Windows Search integration.
+#
+# The Initial Developer of the Original Code is
+# Siddharth Agarwal <sid1337@gmail.com>.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+CPPSRCS = \
+ WSEnable.cpp \
+ $(NULL)
+
+PROGRAM = WSEnable$(BIN_SUFFIX)
+RCINCLUDE = WSEnable.rc
+OS_LIBS += ole32.lib shell32.lib
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/mail/components/search/wsenable/WSEnable.cpp
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; 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 Windows Search integration.
+ *
+ * The Initial Developer of the Original Code is
+ * Siddharth Agarwal <sid1337@gmail.com>.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <SearchAPI.h>
+#include <shellapi.h>
+#include <objbase.h>
+#include <string>
+
+static const CLSID CLSID_CSearchManager = {0x7d096c5f, 0xac08, 0x4f1f, {0xbe, 0xb7, 0x5c, 0x22, 0xc5, 0x17, 0xce, 0x39}};
+static const IID IID_ISearchManager = {0xab310581, 0xac80, 0x11d1, {0x8d, 0xf3, 0x00, 0xc0, 0x4f, 0xb6, 0xef, 0x69}};
+
+static const WCHAR* const sFoldersToIndex[] = {L"\\Mail\\", L"\\ImapMail\\", L"\\News\\"};
+
+struct RegKey
+{
+ HKEY mRoot;
+ LPWSTR mSubKey;
+ LPWSTR mName;
+ LPWSTR mValue;
+
+ RegKey(HKEY aRoot, LPWSTR aSubKey, LPWSTR aName, LPWSTR aValue)
+ : mRoot(aRoot), mSubKey(aSubKey), mName(aName), mValue(aValue) {}
+};
+
+static const RegKey* const sRegKeys[] =
+{
+ new RegKey(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\PropertySystem\\PropertyHandlers\\.wdseml",
+ L"",
+ L"{5FA29220-36A1-40f9-89C6-F4B384B7642E}"),
+ new RegKey(HKEY_CLASSES_ROOT,
+ L".wdseml",
+ L"Content Type",
+ L"message/rfc822"),
+ new RegKey(HKEY_CLASSES_ROOT,
+ L".wdseml\\PersistentHandler",
+ L"",
+ L"{5645c8c4-e277-11cf-8fda-00aa00a14f93}"),
+ new RegKey(HKEY_CLASSES_ROOT,
+ L".wdseml\\shellex\\{8895B1C6-B41F-4C1C-A562-0D564250836F}",
+ L"",
+ L"{b9815375-5d7f-4ce2-9245-c9d4da436930}"),
+ new RegKey(HKEY_LOCAL_MACHINE,
+ L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\explorer\\KindMap",
+ L".wdseml",
+ L"email;communication")
+};
+
+HRESULT GetCrawlScopeManager(ISearchCrawlScopeManager **aCrawlScopeManager)
+{
+ *aCrawlScopeManager = NULL;
+
+ ISearchManager* searchManager;
+ HRESULT hr = CoCreateInstance(CLSID_CSearchManager, NULL, CLSCTX_ALL, IID_ISearchManager, (void**)&searchManager);
+ if (SUCCEEDED(hr))
+ {
+ ISearchCatalogManager* catalogManager;
+ hr = searchManager->GetCatalog(L"SystemIndex", &catalogManager);
+ if (SUCCEEDED(hr))
+ {
+ hr = catalogManager->GetCrawlScopeManager(aCrawlScopeManager);
+ catalogManager->Release();
+ }
+ searchManager->Release();
+ }
+ return hr;
+}
+
+LSTATUS SetRegistryKeys()
+{
+ LSTATUS rv = ERROR_SUCCESS;
+ for (int i = 0; rv == ERROR_SUCCESS && i < _countof(sRegKeys); i++)
+ {
+ const RegKey *key = sRegKeys[i];
+ HKEY subKey;
+ // Since we're administrator, we should be able to do this just fine
+ rv = RegCreateKeyExW(key->mRoot, key->mSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS, NULL, &subKey, NULL);
+ if (rv == ERROR_SUCCESS)
+ rv = RegSetValueExW(subKey, key->mName, 0, REG_SZ, (LPBYTE) key->mValue,
+ (lstrlenW(key->mValue) + 1) * sizeof(WCHAR));
+ RegCloseKey(subKey);
+ }
+
+ return rv;
+}
+
+int APIENTRY wWinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPWSTR lpCmdLine,
+ int nCmdShow)
+{
+ UNREFERENCED_PARAMETER(lpCmdLine);
+
+ HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (SUCCEEDED(hr))
+ {
+ int argc;
+ LPWSTR *argv = CommandLineToArgvW(lpCmdLine, &argc);
+ if (argc != 2)
+ hr = E_INVALIDARG;
+ if (SUCCEEDED(hr))
+ {
+ ISearchCrawlScopeManager* crawlScopeManager;
+ hr = GetCrawlScopeManager(&crawlScopeManager);
+ if (SUCCEEDED(hr))
+ {
+ if (*argv[0] == L'1')
+ {
+ // We first add the required registry entries
+ LSTATUS rv = SetRegistryKeys();
+ if (rv != ERROR_SUCCESS)
+ hr = E_FAIL;
+
+ // Next, we add rules for each of the three folders
+ for (int i = 0; SUCCEEDED(hr) && i < _countof(sFoldersToIndex); i++)
+ {
+ std::wstring path = L"file:///";
+ path.append(argv[1]);
+ path.append(sFoldersToIndex[i]);
+ // Add only if the rule isn't already there
+ BOOL isIncluded = FALSE;
+ hr = crawlScopeManager->IncludedInCrawlScope(path.c_str(), &isIncluded);
+ if (SUCCEEDED(hr) && !isIncluded)
+ hr = crawlScopeManager->AddUserScopeRule(path.c_str(), TRUE, TRUE, TRUE);
+ }
+ }
+ else if (*argv[0] == L'0')
+ {
+ // This is simple, we just exclude the profile dir and override children
+ std::wstring path = L"file:///";
+ path.append(argv[1]);
+ path.append(L"\\*\\");
+ hr = crawlScopeManager->AddUserScopeRule(path.c_str(), FALSE, TRUE, TRUE);
+ }
+ else
+ hr = E_INVALIDARG;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = crawlScopeManager->SaveAll();
+ }
+ crawlScopeManager->Release();
+ }
+ }
+ LocalFree(argv);
+ }
+
+ return hr;
+}
new file mode 100644
--- /dev/null
+++ b/mail/components/search/wsenable/WSEnable.exe.manifest
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<assemblyIdentity
+ version="1.0.0.0"
+ processorArchitecture="*"
+ name="Mozilla.Thunderbird"
+ type="win32"
+/>
+<description>Mozilla Thunderbird Windows Search Integration Handler</description>
+<dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="*"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+</dependency>
+<ms_asmv3:trustInfo xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
+ <ms_asmv3:security>
+ <ms_asmv3:requestedPrivileges>
+ <ms_asmv3:requestedExecutionLevel level="requireAdministrator" uiAccess="false">
+ </ms_asmv3:requestedExecutionLevel>
+ </ms_asmv3:requestedPrivileges>
+ </ms_asmv3:security>
+</ms_asmv3:trustInfo>
+</assembly>
new file mode 100644
--- /dev/null
+++ b/mail/components/search/wsenable/WSEnable.rc
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; 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 Windows Search integration.
+ *
+ * The Initial Developer of the Original Code is
+ * Siddharth Agarwal <sid1337@gmail.com>
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+1 24 "WSEnable.exe.manifest"
new file mode 100644
--- /dev/null
+++ b/mail/components/search/wsenable/module.ver
@@ -0,0 +1,1 @@
+WIN32_MODULE_DESCRIPTION=@MOZ_APP_DISPLAYNAME@ Windows Search Integration Handler
--- a/mail/installer/windows/nsis/shared.nsh
+++ b/mail/installer/windows/nsis/shared.nsh
@@ -370,16 +370,17 @@
StrCpy $1 "$\"$8$\" -osint -compose $\"%1$\""
${AddHandlerValues} "$0\Protocols\mailto" "$1" "$8,0" "${AppRegNameMail} URL" "true" ""
; Vista Capabilities registry keys
WriteRegStr HKLM "$0\Capabilities" "ApplicationDescription" "$(REG_APP_DESC)"
WriteRegStr HKLM "$0\Capabilities" "ApplicationIcon" "$8,0"
WriteRegStr HKLM "$0\Capabilities" "ApplicationName" "${AppRegNameMail}"
WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".eml" "ThunderbirdEML"
+ WriteRegStr HKLM "$0\Capabilities\FileAssociations" ".wdseml" "ThunderbirdEML"
WriteRegStr HKLM "$0\Capabilities\StartMenu" "Mail" "${ClientsRegName}"
WriteRegStr HKLM "$0\Capabilities\URLAssociations" "mailto" "Thunderbird.Url.mailto"
; Vista Registered Application
WriteRegStr HKLM "Software\RegisteredApplications" "${AppRegNameMail}" "$0\Capabilities"
!macroend
!define SetClientsMail "!insertmacro SetClientsMail"
--- a/mail/installer/windows/nsis/uninstaller.nsi
+++ b/mail/installer/windows/nsis/uninstaller.nsi
@@ -233,16 +233,20 @@ Section "Uninstall"
ClearErrors
ReadRegStr $R9 HKCR "ThunderbirdEML" ""
; Don't clean up the file handlers if the ThunderbirdEML key still exists
; since there could be a second installation that may be the default file
; handler.
${If} ${Errors}
${un.RegCleanFileHandler} ".eml" "ThunderbirdEML"
+ ${un.RegCleanFileHandler} ".wdseml" "ThunderbirdEML"
+ DeleteRegValue HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\explorer\KindMap" ".wdseml"
+ ; It doesn't matter if the value didn't exist
+ ClearErrors
${EndIf}
SetShellVarContext all ; Set SHCTX to HKLM
${un.GetSecondInstallPath} "Software\Mozilla" $R9
${If} $R9 == "false"
SetShellVarContext current ; Set SHCTX to HKCU
${un.GetSecondInstallPath} "Software\Mozilla" $R9
${EndIf}
--- a/mail/installer/windows/packages-static
+++ b/mail/installer/windows/packages-static
@@ -172,16 +172,20 @@ bin\components\nsPhishingProtectionAppli
bin\components\nsUrlClassifierListManager.js
bin\components\nsUrlClassifierLib.js
bin\components\url-classifier.xpt
; Address Book autocomplete
bin\components\nsAbAutoCompleteMyDomain.js
bin\components\nsAbAutoCompleteSearch.js
+; Windows Search integration
+bin\components\nsWinSearchIntegration.js
+bin\WSEnable.exe
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Base Package Files
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; xpconnect
bin\components\xpconnect.xpt
; XP widgets/graphics
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/search/searchIntegrationDialogWin.dtd
@@ -0,0 +1,6 @@
+<!ENTITY searchIntegration.engineName "Windows Search">
+<!ENTITY searchIntegration.title "&searchIntegration.engineName; Integration">
+<!ENTITY searchIntegration.description "Would you like to enable &searchIntegration.engineName; to index and search through &brandShortName; mail and news messages?">
+
+<!ENTITY searchIntegration.accept "Enable &searchIntegration.engineName;">
+<!ENTITY searchIntegration.cancel "Don't Enable &searchIntegration.engineName;">
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -122,16 +122,17 @@
locale/@AB_CD@/messenger/preferences/downloadactions.dtd (%chrome/messenger/preferences/downloadactions.dtd)
locale/@AB_CD@/messenger/preferences/changeaction.dtd (%chrome/messenger/preferences/changeaction.dtd)
locale/@AB_CD@/messenger/preferences/fonts.dtd (%chrome/messenger/preferences/fonts.dtd)
locale/@AB_CD@/messenger/preferences/offline.dtd (%chrome/messenger/preferences/offline.dtd)
locale/@AB_CD@/messenger/preferences/notifications.dtd (%chrome/messenger/preferences/notifications.dtd)
locale/@AB_CD@/messenger/preferences/preferences.properties (%chrome/messenger/preferences/preferences.properties)
locale/@AB_CD@/messenger/migration/migration.dtd (%chrome/messenger/migration/migration.dtd)
locale/@AB_CD@/messenger/migration/migration.properties (%chrome/messenger/migration/migration.properties)
+ locale/@AB_CD@/messenger/search/searchIntegrationDialogWin.dtd (%chrome/messenger/search/searchIntegrationDialogWin.dtd)
% locale messenger-mapi @AB_CD@ %locale/@AB_CD@/messenger-mapi/
locale/@AB_CD@/messenger-mapi/mapi.properties (%chrome/messenger-mapi/mapi.properties)
% locale messenger-newsblog @AB_CD@ %locale/@AB_CD@/messenger-newsblog/
locale/@AB_CD@/messenger-newsblog/newsblog.dtd (%chrome/messenger-newsblog/newsblog.dtd)
locale/@AB_CD@/messenger-newsblog/newsblog.properties (%chrome/messenger-newsblog/newsblog.properties)
locale/@AB_CD@/messenger-newsblog/feed-subscriptions.dtd (%chrome/messenger-newsblog/feed-subscriptions.dtd)
locale/@AB_CD@/messenger-newsblog/feed-properties.dtd (%chrome/messenger-newsblog/feed-properties.dtd)
locale/@AB_CD@/messenger-newsblog/am-newsblog.properties (%chrome/messenger-newsblog/am-newsblog.properties)