mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 06:38:36 +00:00
bug 263546: move external protocol warning down a level, r=jsr,sr=darin
This commit is contained in:
parent
b0a51a539c
commit
430d42c69d
@ -191,7 +191,6 @@ pref("privacy.popups.policy", 1);
|
||||
pref("privacy.popups.usecustom", true);
|
||||
pref("privacy.popups.firstTime", true);
|
||||
|
||||
pref("network.protocols.useSystemDefaults", false); // set to true if user links should use system default handlers
|
||||
pref("network.cookie.cookieBehavior", 0); // cookies enabled
|
||||
pref("network.cookie.enableForCurrentSessionOnly", false);
|
||||
|
||||
@ -240,8 +239,16 @@ pref("signon.rememberSignons", true);
|
||||
pref("signon.expireMasterPassword", false);
|
||||
pref("signon.SignonFileName", "signons.txt");
|
||||
|
||||
// We want to make sure mail URLs are handled externally...
|
||||
pref("network.protocol-handler.external.mailto", true); // for mail
|
||||
pref("network.protocol-handler.external.news" , true); // for news
|
||||
pref("network.protocol-handler.external.news", true); // for news
|
||||
pref("network.protocol-handler.external.snews", true); // for secure news
|
||||
pref("network.protocol-handler.external.nntp", true); // also news
|
||||
// ...without warning dialogs
|
||||
pref("network.protocol-handler.warn-external.mailto", false);
|
||||
pref("network.protocol-handler.warn-external.news", false);
|
||||
pref("network.protocol-handler.warn-external.snews", false);
|
||||
pref("network.protocol-handler.warn-external.nntp", false);
|
||||
|
||||
// By default, all protocol handlers are exposed. This means that
|
||||
// the browser will respond to openURL commands for all URL types.
|
||||
@ -249,6 +256,9 @@ pref("network.protocol-handler.external.news" , true); // for news
|
||||
// failing over to the system handlers.
|
||||
pref("network.protocol-handler.expose-all", true);
|
||||
pref("network.protocol-handler.expose.mailto", false);
|
||||
pref("network.protocol-handler.expose.news", false);
|
||||
pref("network.protocol-handler.expose.snews", false);
|
||||
pref("network.protocol-handler.expose.nntp", false);
|
||||
|
||||
// Default security warning dialogs to show once.
|
||||
pref("security.warn_entering_secure.show_once", true);
|
||||
|
@ -536,7 +536,6 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
{
|
||||
PRBool earlyReturn = PR_FALSE;
|
||||
{
|
||||
// defer to an external protocol handler if necessary...
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService = do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
|
||||
@ -549,17 +548,11 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
|
||||
PRBool isExposed;
|
||||
nsresult rv = extProtService->IsExposedProtocol(scheme.get(), &isExposed);
|
||||
if (NS_SUCCEEDED(rv) && !isExposed) {
|
||||
rv = extProtService->LoadUrl(aURI);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
earlyReturn = PR_TRUE;
|
||||
else
|
||||
NS_WARNING("failed to launch external protocol handler");
|
||||
return extProtService->LoadUrl(aURI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (earlyReturn)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aContent));
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED);
|
||||
|
@ -100,19 +100,20 @@ pref("image.animation_mode", "normal");
|
||||
// prevents necko connecting to ports 1-5 unless the protocol
|
||||
// overrides.
|
||||
|
||||
// Default action for unlisted external protocol handlers
|
||||
pref("network.protocol-handler.external-default", true); // OK to load
|
||||
pref("network.protocol-handler.warn-external-default", true); // warn before load
|
||||
|
||||
// Prevent using external protocol handlers for these schemes
|
||||
pref("network.protocol-handler.external.hcp", false);
|
||||
pref("network.protocol-handler.external.vbscript", false);
|
||||
pref("network.protocol-handler.external.javascript", false);
|
||||
pref("network.protocol-handler.external.data", false);
|
||||
pref("network.protocol-handler.external.ms-help", false);
|
||||
pref("network.protocol-handler.external.vnd.ms.radio", false);
|
||||
pref("network.protocol-handler.external.help", false);
|
||||
pref("network.protocol-handler.external.disk", false);
|
||||
|
||||
// Default action for unlisted external protocol handlers
|
||||
// 0 == never load, 1 == always load, 2 == ask the user
|
||||
pref("network.protocol-handler.external-default", 2);
|
||||
|
||||
// An exposed protocol handler is one that can be used in all contexts. A
|
||||
// non-exposed protocol handler is one that can only be used internally by the
|
||||
// application. For example, a non-exposed protocol would not be loaded by the
|
||||
|
@ -436,10 +436,15 @@ pref("image.animation_mode", "normal");
|
||||
// prevents necko connecting to ports 1-5 unless the protocol
|
||||
// overrides.
|
||||
|
||||
// Default action for unlisted external protocol handlers
|
||||
pref("network.protocol-handler.external-default", true); // OK to load
|
||||
pref("network.protocol-handler.warn-external-default", true); // warn before load
|
||||
|
||||
// Prevent using external protocol handlers for these schemes
|
||||
pref("network.protocol-handler.external.hcp", false);
|
||||
pref("network.protocol-handler.external.vbscript", false);
|
||||
pref("network.protocol-handler.external.javascript", false);
|
||||
pref("network.protocol-handler.external.data", false);
|
||||
pref("network.protocol-handler.external.ms-help", false);
|
||||
pref("network.protocol-handler.external.shell", false);
|
||||
pref("network.protocol-handler.external.vnd.ms.radio", false);
|
||||
@ -448,10 +453,6 @@ pref("network.protocol-handler.external.disk", false);
|
||||
pref("network.protocol-handler.external.disks", false);
|
||||
pref("network.protocol-handler.external.afp", false);
|
||||
|
||||
// Default action for unlisted external protocol handlers
|
||||
// 0 == never load, 1 == always load, 2 == ask the user
|
||||
pref("network.protocol-handler.external-default", 2);
|
||||
|
||||
// An exposed protocol handler is one that can be used in all contexts. A
|
||||
// non-exposed protocol handler is one that can only be used internally by the
|
||||
// application. For example, a non-exposed protocol would not be loaded by the
|
||||
|
@ -76,6 +76,7 @@ REQUIRES = xpcom \
|
||||
intl \
|
||||
uconv \
|
||||
docshell \
|
||||
windowwatcher \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_PHOENIX
|
||||
|
@ -81,7 +81,7 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOSHelperAppService::LoadUrl(nsIURI * aURL)
|
||||
nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL)
|
||||
{
|
||||
LOG(("-- nsOSHelperAppService::LoadUrl\n"));
|
||||
nsresult rv = NS_OK;
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
|
||||
// override nsIExternalProtocolService methods
|
||||
NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
|
||||
NS_IMETHOD LoadUrl(nsIURI * aURL);
|
||||
nsresult LoadUriInternal(nsIURI * aURL);
|
||||
|
||||
// GetFileTokenForPath must be implemented by each platform.
|
||||
// platformAppPath --> a platform specific path to an application that we got out of the
|
||||
|
@ -118,7 +118,7 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOSHelperAppService::LoadUrl(nsIURI * aURL)
|
||||
nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL)
|
||||
{
|
||||
nsCAutoString url;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
|
||||
// override nsIExternalProtocolService methods
|
||||
NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
|
||||
NS_IMETHOD LoadUrl(nsIURI * aURL);
|
||||
nsresult LoadUriInternal(nsIURI * aURL);
|
||||
|
||||
// method overrides --> used to hook the mime service into internet config....
|
||||
NS_IMETHOD GetFromTypeAndExtension(const nsACString& aType, const nsACString& aFileExt, nsIMIMEInfo ** aMIMEInfo);
|
||||
|
@ -102,6 +102,7 @@
|
||||
#include "nsIMIMEHeaderParam.h"
|
||||
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
|
||||
#include "nsIGlobalHistory.h" // to mark downloads as visited
|
||||
|
||||
@ -1063,8 +1064,211 @@ NS_IMETHODIMP nsExternalHelperAppService::IsExposedProtocol(const char * aProtoc
|
||||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::LoadUrl(nsIURI * aURL)
|
||||
{
|
||||
// this method should only be implemented by each OS specific implementation of this service.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return LoadURI(aURL, nsnull);
|
||||
}
|
||||
|
||||
|
||||
// nsExternalHelperAppService::LoadURI() may now pose a confirm dialog
|
||||
// that existing callers aren't expecting. We must do it on an event
|
||||
// callback to make sure we don't hang someone up.
|
||||
|
||||
struct extLoadRequest : PLEvent {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsIPrompt> prompt;
|
||||
};
|
||||
|
||||
void *PR_CALLBACK
|
||||
nsExternalHelperAppService::handleExternalLoadEvent(PLEvent *event)
|
||||
{
|
||||
extLoadRequest* req = NS_STATIC_CAST(extLoadRequest*, event);
|
||||
if (req && sSrv && sSrv->isExternalLoadOK(req->uri, req->prompt))
|
||||
sSrv->LoadUriInternal(req->uri);
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK destroyExternalLoadEvent(PLEvent *event)
|
||||
{
|
||||
delete NS_STATIC_CAST(extLoadRequest*, event);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::LoadURI(nsIURI * aURL, nsIPrompt * aPrompt)
|
||||
{
|
||||
// post external load event
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
extLoadRequest *event = new extLoadRequest;
|
||||
if (!event)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
event->uri = aURL;
|
||||
event->prompt = aPrompt;
|
||||
PL_InitEvent(event, nsnull, handleExternalLoadEvent, destroyExternalLoadEvent);
|
||||
|
||||
rv = eventQ->PostEvent(event);
|
||||
if (NS_FAILED(rv))
|
||||
PL_DestroyEvent(event);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// helper routines used by LoadURI to check whether we're allowed
|
||||
// to load external schemes and whether or not to warn the user
|
||||
|
||||
static const char kExternalProtocolPrefPrefix[] = "network.protocol-handler.external.";
|
||||
static const char kExternalProtocolDefaultPref[] = "network.protocol-handler.external-default";
|
||||
static const char kExternalWarningPrefPrefix[] = "network.protocol-handler.warn-external.";
|
||||
static const char kExternalWarningDefaultPref[] = "network.protocol-handler.warn-external-default";
|
||||
|
||||
|
||||
PRBool nsExternalHelperAppService::isExternalLoadOK(nsIURI* aURL, nsIPrompt* aPrompt)
|
||||
{
|
||||
if (!aURL)
|
||||
return PR_FALSE;
|
||||
|
||||
nsCAutoString scheme;
|
||||
aURL->GetScheme(scheme);
|
||||
if (scheme.IsEmpty())
|
||||
return PR_FALSE; // must have a scheme
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (!prefs)
|
||||
return PR_FALSE; // deny if we can't check prefs
|
||||
|
||||
|
||||
// Deny load if the prefs say to do so
|
||||
nsCAutoString externalPref(kExternalProtocolPrefPrefix);
|
||||
externalPref += scheme;
|
||||
PRBool allowLoad = PR_FALSE;
|
||||
nsresult rv = prefs->GetBoolPref(externalPref.get(), &allowLoad);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// no scheme-specific value, check the default
|
||||
rv = prefs->GetBoolPref(kExternalProtocolDefaultPref, &allowLoad);
|
||||
}
|
||||
if (NS_FAILED(rv) || !allowLoad)
|
||||
return PR_FALSE; // explicitly denied or missing default pref
|
||||
|
||||
|
||||
// allowLoad is now true. See whether we have to ask the user
|
||||
nsCAutoString warningPref(kExternalWarningPrefPrefix);
|
||||
warningPref += scheme;
|
||||
PRBool warn = PR_TRUE;
|
||||
rv = prefs->GetBoolPref(warningPref.get(), &warn);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// no scheme-specific value, check the default
|
||||
rv = prefs->GetBoolPref(kExternalWarningDefaultPref, &warn);
|
||||
}
|
||||
|
||||
|
||||
if (NS_FAILED(rv) || warn)
|
||||
{
|
||||
// explicit "warn" setting or missing default pref:
|
||||
// we must ask the user before loading this type externally
|
||||
PRBool remember = PR_FALSE;
|
||||
allowLoad = promptForScheme(aURL, aPrompt, &remember);
|
||||
|
||||
if (remember)
|
||||
{
|
||||
if (allowLoad)
|
||||
// suppress future warnings for this scheme
|
||||
prefs->SetBoolPref(warningPref.get(), PR_FALSE);
|
||||
else
|
||||
// prevent externally loading this scheme in the future
|
||||
prefs->SetBoolPref(externalPref.get(), PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return allowLoad;
|
||||
}
|
||||
|
||||
PRBool nsExternalHelperAppService::promptForScheme(nsIURI* aURI,
|
||||
nsIPrompt* aPrompt,
|
||||
PRBool *aRemember)
|
||||
{
|
||||
// if no prompt passed in get one from the windowwatcher
|
||||
nsCOMPtr<nsIPrompt> prompt(aPrompt);
|
||||
if (!prompt)
|
||||
{
|
||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
||||
if (wwatch)
|
||||
wwatch->GetNewPrompter(0, getter_AddRefs(prompt));
|
||||
}
|
||||
if (!prompt) {
|
||||
NS_ERROR("No prompt to warn user about external load, denying");
|
||||
return PR_FALSE; // told to warn but no prompt: deny
|
||||
}
|
||||
|
||||
// load the strings we need
|
||||
nsCOMPtr<nsIStringBundleService> sbSvc(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
|
||||
if (!sbSvc) {
|
||||
NS_ERROR("Couldn't load StringBundleService");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStringBundle> appstrings;
|
||||
nsresult rv = sbSvc->CreateBundle("chrome://global/locale/appstrings.properties",
|
||||
getter_AddRefs(appstrings));
|
||||
if (NS_FAILED(rv) || !appstrings) {
|
||||
NS_ERROR("Failed to create appstrings.properties bundle");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCAutoString spec;
|
||||
aURI->GetSpec(spec);
|
||||
NS_ConvertUTF8toUTF16 uri(spec);
|
||||
|
||||
nsCAutoString asciischeme;
|
||||
aURI->GetScheme(asciischeme);
|
||||
NS_ConvertUTF8toUTF16 scheme(asciischeme);
|
||||
|
||||
nsXPIDLString desc;
|
||||
GetApplicationDescription(asciischeme, desc);
|
||||
|
||||
nsXPIDLString title;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolTitle").get(),
|
||||
getter_Copies(title));
|
||||
nsXPIDLString checkMsg;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolChkMsg").get(),
|
||||
getter_Copies(checkMsg));
|
||||
nsXPIDLString launchBtn;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolLaunchBtn").get(),
|
||||
getter_Copies(launchBtn));
|
||||
|
||||
if (desc.IsEmpty())
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolUnknown").get(),
|
||||
getter_Copies(desc));
|
||||
|
||||
nsXPIDLString message;
|
||||
const PRUnichar* msgArgs[] = { scheme.get(), uri.get(), desc.get() };
|
||||
appstrings->FormatStringFromName(NS_LITERAL_STRING("externalProtocolPrompt").get(),
|
||||
msgArgs,
|
||||
NS_ARRAY_LENGTH(msgArgs),
|
||||
getter_Copies(message));
|
||||
|
||||
if (scheme.IsEmpty() || uri.IsEmpty() || title.IsEmpty() ||
|
||||
checkMsg.IsEmpty() || launchBtn.IsEmpty() || message.IsEmpty() ||
|
||||
desc.IsEmpty())
|
||||
return PR_FALSE;
|
||||
|
||||
// all pieces assembled, now we can pose the dialog
|
||||
PRInt32 choice = 1; // assume "cancel" in case of failure
|
||||
rv = prompt->ConfirmEx(title.get(), message.get(),
|
||||
nsIPrompt::BUTTON_DELAY_ENABLE +
|
||||
nsIPrompt::BUTTON_POS_1_DEFAULT +
|
||||
(nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) +
|
||||
(nsIPrompt::BUTTON_TITLE_CANCEL * nsIPrompt::BUTTON_POS_1),
|
||||
launchBtn.get(), 0, 0, checkMsg.get(),
|
||||
aRemember, &choice);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && choice == 0)
|
||||
return PR_TRUE;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExternalHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval)
|
||||
@ -1811,6 +2015,11 @@ nsresult nsExternalAppHandler::ExecuteDesiredAction()
|
||||
// XXX Put progress dialog in barber-pole mode
|
||||
// and change text to say "Copying from:".
|
||||
rv = MoveFile(mFinalFileDestination);
|
||||
if (NS_SUCCEEDED(rv) && action == nsIMIMEInfo::saveToDisk)
|
||||
{
|
||||
nsCOMPtr<nsILocalFile> destfile(do_QueryInterface(mFinalFileDestination));
|
||||
sSrv->FixFilePermissions(destfile);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify dialog that download is complete.
|
||||
@ -1990,7 +2199,6 @@ nsresult nsExternalAppHandler::MoveFile(nsIFile * aNewFileLocation)
|
||||
if (directoryLocation)
|
||||
{
|
||||
rv = mTempFile->MoveToNative(directoryLocation, fileName);
|
||||
sSrv->FixFilePermissions(fileToUse);
|
||||
}
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
|
@ -70,6 +70,8 @@
|
||||
#include "nsIObserver.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsIPrompt.h"
|
||||
#include "nsEventQueueUtils.h"
|
||||
|
||||
class nsExternalAppHandler;
|
||||
class nsIMIMEInfo;
|
||||
@ -309,6 +311,16 @@ protected:
|
||||
* Array for the files that should be deleted
|
||||
*/
|
||||
nsCOMArray<nsILocalFile> mTemporaryFilesList;
|
||||
|
||||
/**
|
||||
* OS-specific loading of external URLs
|
||||
*/
|
||||
virtual NS_HIDDEN_(nsresult) LoadUriInternal(nsIURI * aURL) = 0;
|
||||
NS_HIDDEN_(PRBool) isExternalLoadOK(nsIURI* aURI, nsIPrompt* aPrompt);
|
||||
NS_HIDDEN_(PRBool) promptForScheme(nsIURI* aURI, nsIPrompt* aPrompt, PRBool *aRemember);
|
||||
|
||||
// friend event handler that accesses the external loading functions
|
||||
static void *PR_CALLBACK handleExternalLoadEvent(PLEvent *event);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -61,7 +61,6 @@
|
||||
#include "nsIExternalProtocolService.h"
|
||||
|
||||
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
|
||||
static const char kExternalProtocolPrefPrefix[] = "network.protocol-handler.external.";
|
||||
|
||||
|
||||
|
||||
@ -83,15 +82,14 @@ public:
|
||||
|
||||
nsresult SetURI(nsIURI*);
|
||||
|
||||
private:
|
||||
nsresult OpenURL();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIURI> mUrl;
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsresult mStatus;
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
PRBool PromptForScheme(nsIURI *aURI);
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsExtProtocolChannel)
|
||||
@ -168,158 +166,29 @@ nsresult nsExtProtocolChannel::SetURI(nsIURI* aURI)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool nsExtProtocolChannel::PromptForScheme(nsIURI* aURI)
|
||||
{
|
||||
// deny the load if we aren't able to ask but prefs say we should
|
||||
nsCAutoString scheme;
|
||||
nsresult rv = aURI->GetScheme(scheme);
|
||||
if (!mCallbacks) {
|
||||
NS_WARNING("Notification Callbacks not set!");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrompt> prompt = do_GetInterface(mCallbacks);
|
||||
if (!prompt) {
|
||||
NS_WARNING("No prompt interface on channel");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIStringBundleService> sbSvc(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
|
||||
if (!sbSvc) {
|
||||
NS_WARNING("Couldn't load StringBundleService");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsXPIDLString desc;
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
if (extProtService)
|
||||
extProtService->GetApplicationDescription(scheme, desc);
|
||||
|
||||
nsCOMPtr<nsIStringBundle> appstrings;
|
||||
rv = sbSvc->CreateBundle("chrome://global/locale/appstrings.properties",
|
||||
getter_AddRefs(appstrings));
|
||||
if (NS_FAILED(rv) || !appstrings) {
|
||||
NS_WARNING("Failed to create appstrings.properties bundle");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCAutoString spec;
|
||||
aURI->GetSpec(spec);
|
||||
NS_ConvertUTF8toUTF16 uri(spec);
|
||||
NS_ConvertUTF8toUTF16 utf16scheme(scheme);
|
||||
|
||||
nsXPIDLString title;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolTitle").get(),
|
||||
getter_Copies(title));
|
||||
nsXPIDLString checkMsg;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolChkMsg").get(),
|
||||
getter_Copies(checkMsg));
|
||||
nsXPIDLString launchBtn;
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolLaunchBtn").get(),
|
||||
getter_Copies(launchBtn));
|
||||
|
||||
if (desc.IsEmpty())
|
||||
appstrings->GetStringFromName(NS_LITERAL_STRING("externalProtocolUnknown").get(),
|
||||
getter_Copies(desc));
|
||||
|
||||
|
||||
nsXPIDLString message;
|
||||
const PRUnichar* msgArgs[] = { utf16scheme.get(), uri.get(), desc.get() };
|
||||
appstrings->FormatStringFromName(NS_LITERAL_STRING("externalProtocolPrompt").get(),
|
||||
msgArgs,
|
||||
NS_ARRAY_LENGTH(msgArgs),
|
||||
getter_Copies(message));
|
||||
|
||||
if (utf16scheme.IsEmpty() || uri.IsEmpty() || title.IsEmpty() ||
|
||||
checkMsg.IsEmpty() || launchBtn.IsEmpty() || message.IsEmpty() ||
|
||||
desc.IsEmpty())
|
||||
return PR_FALSE;
|
||||
|
||||
// all pieces assembled, now we can pose the dialog
|
||||
PRBool allowLoad = PR_FALSE;
|
||||
PRBool remember = PR_FALSE;
|
||||
PRInt32 choice = 1; // assume "cancel" in case of failure
|
||||
rv = prompt->ConfirmEx(title.get(), message.get(),
|
||||
nsIPrompt::BUTTON_DELAY_ENABLE +
|
||||
nsIPrompt::BUTTON_POS_1_DEFAULT +
|
||||
(nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) +
|
||||
(nsIPrompt::BUTTON_TITLE_CANCEL * nsIPrompt::BUTTON_POS_1),
|
||||
launchBtn.get(), 0, 0, checkMsg.get(),
|
||||
&remember, &choice);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
if (choice == 0)
|
||||
allowLoad = PR_TRUE;
|
||||
|
||||
if (remember)
|
||||
{
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
if (prefs)
|
||||
{
|
||||
nsCAutoString prefname(kExternalProtocolPrefPrefix);
|
||||
prefname += scheme;
|
||||
prefs->SetBoolPref(prefname.get(), allowLoad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allowLoad;
|
||||
}
|
||||
|
||||
nsresult nsExtProtocolChannel::OpenURL()
|
||||
{
|
||||
nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
||||
nsCAutoString urlScheme;
|
||||
mUrl->GetScheme(urlScheme);
|
||||
|
||||
if (extProtService)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nsCAutoString urlScheme;
|
||||
mUrl->GetScheme(urlScheme);
|
||||
PRBool haveHandler = PR_FALSE;
|
||||
extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler);
|
||||
NS_ASSERTION(haveHandler, "Why do we have a channel for this url if we don't support the protocol?");
|
||||
#endif
|
||||
|
||||
// Check that it's OK to hand this scheme off to the OS
|
||||
|
||||
PRBool allowLoad = PR_FALSE;
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||
|
||||
if (prefs)
|
||||
// get an nsIPrompt from the channel if we can
|
||||
nsCOMPtr<nsIPrompt> prompt;
|
||||
if (mCallbacks)
|
||||
{
|
||||
// check whether it's explicitly approved or denied in prefs
|
||||
nsCAutoString schemePref(kExternalProtocolPrefPrefix);
|
||||
schemePref += urlScheme;
|
||||
|
||||
nsresult rv = prefs->GetBoolPref(schemePref.get(), &allowLoad);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
// scheme not explicitly listed, what is the default action?
|
||||
const PRInt32 kExternalProtocolNever = 0;
|
||||
const PRInt32 kExternalProtocolAlways = 1;
|
||||
const PRInt32 kExternalProtocolAsk = 2;
|
||||
|
||||
PRInt32 externalDefault = kExternalProtocolAsk;
|
||||
prefs->GetIntPref("network.protocol-handler.external-default",
|
||||
&externalDefault);
|
||||
|
||||
if (externalDefault == kExternalProtocolAlways)
|
||||
{
|
||||
// original behavior -- just do it
|
||||
allowLoad = PR_TRUE;
|
||||
}
|
||||
else if (externalDefault == kExternalProtocolAsk)
|
||||
{
|
||||
allowLoad = PromptForScheme(mUrl);
|
||||
}
|
||||
}
|
||||
mCallbacks->GetInterface(NS_GET_IID(nsIPrompt), getter_AddRefs(prompt));
|
||||
}
|
||||
|
||||
if (allowLoad)
|
||||
return extProtService->LoadUrl(mUrl);
|
||||
return extProtService->LoadURI(mUrl, prompt);
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -329,44 +198,9 @@ NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
|
||||
return NS_ERROR_NO_CONTENT; // force caller to abort.
|
||||
}
|
||||
|
||||
static void *PR_CALLBACK handleExtProtoEvent(PLEvent *event)
|
||||
{
|
||||
nsExtProtocolChannel *channel =
|
||||
NS_STATIC_CAST(nsExtProtocolChannel*, PL_GetEventOwner(event));
|
||||
|
||||
NS_ASSERTION(channel, "Where has the channel gone?");
|
||||
channel->OpenURL();
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static void PR_CALLBACK destroyExtProtoEvent(PLEvent *event)
|
||||
{
|
||||
nsExtProtocolChannel *channel =
|
||||
NS_STATIC_CAST(nsExtProtocolChannel*, PL_GetEventOwner(event));
|
||||
NS_ASSERTION(channel, "Where has the channel gone?");
|
||||
NS_RELEASE(channel);
|
||||
delete event;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
|
||||
{
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PLEvent *event = new PLEvent;
|
||||
if (event)
|
||||
{
|
||||
NS_ADDREF_THIS();
|
||||
PL_InitEvent(event, this, handleExtProtoEvent, destroyExtProtoEvent);
|
||||
|
||||
rv = eventQ->PostEvent(event);
|
||||
if (NS_FAILED(rv))
|
||||
PL_DestroyEvent(event);
|
||||
}
|
||||
|
||||
OpenURL();
|
||||
return NS_ERROR_NO_CONTENT; // force caller to abort.
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIFile;
|
||||
interface nsIPrompt;
|
||||
|
||||
/**
|
||||
* The external protocol service is used for finding and launching
|
||||
@ -78,6 +79,15 @@ interface nsIExternalProtocolService : nsISupports
|
||||
*/
|
||||
void loadUrl (in nsIURI aURL);
|
||||
|
||||
/**
|
||||
* Used to load a URI via an external application. Might prompt the user for
|
||||
* permission to load the external application. Replaces loadUrl()
|
||||
*
|
||||
* @param aURI The URI to load
|
||||
* @param aPrompt If null we grab one from windowwatcher if we need it
|
||||
*/
|
||||
void loadURI(in nsIURI aURI, in nsIPrompt aPrompt);
|
||||
|
||||
/**
|
||||
* Gets a human-readable description for the application responsible for
|
||||
* handling a specific protocol.
|
||||
@ -91,4 +101,4 @@ interface nsIExternalProtocolService : nsISupports
|
||||
* possible to get a description for it.
|
||||
*/
|
||||
AString getApplicationDescription(in AUTF8String aScheme);
|
||||
};
|
||||
};
|
||||
|
@ -1158,7 +1158,7 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOSHelperAppService::LoadUrl(nsIURI * aURL)
|
||||
nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL)
|
||||
{
|
||||
LOG(("-- nsOSHelperAppService::LoadUrl\n"));
|
||||
nsCOMPtr<nsIPref> thePrefsService(do_GetService(NS_PREF_CONTRACTID));
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
|
||||
// override nsIExternalProtocolService methods
|
||||
NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
|
||||
NS_IMETHOD LoadUrl(nsIURI * aURL);
|
||||
nsresult LoadUriInternal(nsIURI * aURL);
|
||||
|
||||
protected:
|
||||
already_AddRefed<nsMIMEInfoOS2> GetFromType(const nsCString& aMimeType);
|
||||
|
@ -1258,7 +1258,7 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsOSHelperAppService::LoadUrl(nsIURI * aURI)
|
||||
nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURI)
|
||||
{
|
||||
// Gets a string pref network.protocol-handler.app.<scheme>
|
||||
// and executes it
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
|
||||
// override nsIExternalProtocolService methods
|
||||
NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
|
||||
NS_IMETHOD LoadUrl(nsIURI * aURL);
|
||||
nsresult LoadUriInternal(nsIURI * aURL);
|
||||
NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
|
||||
|
||||
// GetFileTokenForPath must be implemented by each platform.
|
||||
|
@ -224,7 +224,7 @@ NS_IMETHODIMP nsOSHelperAppService::ExternalProtocolHandlerExists(const char * a
|
||||
|
||||
// this implementation was pretty much copied verbatime from Tony Robinson's code in nsExternalProtocolWin.cpp
|
||||
|
||||
NS_IMETHODIMP nsOSHelperAppService::LoadUrl(nsIURI * aURL)
|
||||
nsresult nsOSHelperAppService::LoadUriInternal(nsIURI * aURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
|
||||
// override nsIExternalProtocolService methods
|
||||
NS_IMETHOD ExternalProtocolHandlerExists(const char * aProtocolScheme, PRBool * aHandlerExists);
|
||||
NS_IMETHOD LoadUrl(nsIURI * aURL);
|
||||
nsresult LoadUriInternal(nsIURI * aURL);
|
||||
NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, nsAString& _retval);
|
||||
|
||||
// method overrides for windows registry look up steps....
|
||||
|
Loading…
x
Reference in New Issue
Block a user