diff --git a/mozilla/uriloader/base/nsCURILoader.idl b/mozilla/uriloader/base/nsCURILoader.idl index 505ea2ab402..62075506fca 100644 --- a/mozilla/uriloader/base/nsCURILoader.idl +++ b/mozilla/uriloader/base/nsCURILoader.idl @@ -51,4 +51,7 @@ nsIURILoader #define NS_DOCUMENTLOADER_SERVICE_PROGID \ "component://netscape/docloaderservice" +#define NS_CONTENT_HANDLER_PROGID "component://netscape/uriloader/content-handler" +#define NS_CONTENT_HANDLER_PROGID_PREFIX NS_CONTENT_HANDLER_PROGID "?type=" + %} diff --git a/mozilla/uriloader/base/nsIContentHandler.idl b/mozilla/uriloader/base/nsIContentHandler.idl index 022579b7a12..bd8172b32bc 100644 --- a/mozilla/uriloader/base/nsIContentHandler.idl +++ b/mozilla/uriloader/base/nsIContentHandler.idl @@ -34,7 +34,3 @@ interface nsIContentHandler : nsISupports in nsIChannel aChannel); }; -%{ C++ -#define NS_CONTENT_HANDLER_PROGID "component://netscape/uriloader/content-handler" -#define NS_CONTENT_HANDLER_PROGID_PREFIX NS_CONTENT_HANDLER_PROGID "?type=" -%} diff --git a/mozilla/uriloader/base/nsIURIContentListener.idl b/mozilla/uriloader/base/nsIURIContentListener.idl index 314ef8493cd..c14d15abad1 100644 --- a/mozilla/uriloader/base/nsIURIContentListener.idl +++ b/mozilla/uriloader/base/nsIURIContentListener.idl @@ -50,10 +50,10 @@ interface nsIURIContentListener : nsISupports */ void getProtocolHandler(in nsIURI aURI, out nsIProtocolHandler aProtocolHandler); - /* The URIDispatcher will give the content listener a shot at handling - the content before it tries other means. If the content listener - wants to handle the content then it should return a stream listener - the data should be pushed into. + /* doContent --> When the content listener is expected to process the + content, the uri loader calls doContent. doContent needs to return a + nsIStreamListener which the uri loader will push the content into. + aContentType --> the content type we need to handle aCommand --> verb for the action (this comes from layout???) aWindowTarget --> name of the target window if any @@ -72,10 +72,38 @@ interface nsIURIContentListener : nsISupports out nsIStreamListener aContentHandler, out boolean aAbortProcess); - /* returns true if we can handle the content and false if we can't. + /* When given a uri to dispatch, if the load type is a user click, + then the uri loader tries to find a preferred content handler for + this content type. The thought is that many content listeners may + be able to handle the same content type if they have to. i.e. the mail + content window can handle text/html just like a browser window content + listener. However, if the user clicks on a link with text/html content, + we'd like the browser window to handle that content and not the mail window + where the user may have clicked the link. That's why we have isPreferred. + + aContentType --> the content type to handle + aCommand --> verb for the action + aWindowTarget --> name of the target window (if any) aDesiredContentType --> yes, we can accept aContentType but we would - like it converted to aDesiredContentType. This argument can be null if - you want the content directly as aContentType */ + like it converted to aDesiredContentType. This argument can be null if + you want the content directly as aContentType + boolean --> return true if you are a preferred content handler for aContentType + and false otherwise. + */ + boolean isPreferred(in string aContentType, + in nsURILoadCommand aCommand, + in string aWindowTarget, + out string aDesiredContentType); + + /* When given a uri to dispatch, if the load type is anything but user click, + the uri loader will call canHandleContent to see if the content listener + can handle the content. The arguments are the same as isPreferred. + + Note: I really envision canHandleContent as a method implemented by the docshell + as the implementation is generic to all doc shells. The IsPreferred decision + is a decision made by a top level application content listener that sits at the + top of the docshell hiearchy. + */ boolean canHandleContent(in string aContentType, in nsURILoadCommand aCommand, in string aWindowTarget, diff --git a/mozilla/uriloader/base/nsURILoader.cpp b/mozilla/uriloader/base/nsURILoader.cpp index 27a66cfeec5..b7eee117f0f 100644 --- a/mozilla/uriloader/base/nsURILoader.cpp +++ b/mozilla/uriloader/base/nsURILoader.cpp @@ -575,48 +575,79 @@ nsresult nsURILoader::SetupLoadCookie(nsISupports * aWindowContext, nsISupports return rv; } -nsresult nsURILoader::DispatchContent(const char * aContentType, - nsURILoadCommand aCommand, - const char * aWindowTarget, - nsIChannel * aChannel, - nsISupports * aCtxt, - nsIURIContentListener * aContentListener, - char ** aContentTypeToUse, - nsIURIContentListener ** aContentListenerToUse, - PRBool * aAbortProcess) +PRBool nsURILoader::ShouldHandleContent(nsIURIContentListener * aCntListener, + const char * aContentType, + nsURILoadCommand aCommand, + const char * aWindowTarget, + char ** aContentTypeToUse) { + PRBool foundContentHandler = PR_FALSE; + if (aCommand == nsIURILoader::viewUserClick) + aCntListener->IsPreferred(aContentType, aCommand, aWindowTarget, + aContentTypeToUse, + &foundContentHandler); + else + aCntListener->CanHandleContent(aContentType, aCommand, aWindowTarget, + aContentTypeToUse, + &foundContentHandler); + return foundContentHandler; +} + +NS_IMETHODIMP nsURILoader::DispatchContent(const char * aContentType, + nsURILoadCommand aCommand, + const char * aWindowTarget, + nsIChannel * aChannel, + nsISupports * aCtxt, + nsIURIContentListener * aContentListener, + char ** aContentTypeToUse, + nsIURIContentListener ** aContentListenerToUse, + PRBool * aAbortProcess) +{ + NS_ENSURE_ARG(aContentType); + NS_ENSURE_ARG(aChannel); + // okay, now we've discovered the content type. We need to do the following: - // (1) Give our uri content listener first crack at handling this content type. + // (1) if aCommand is user click, we need to find the Preferred content handler + // for this type... + // (2) if aCommand is any other value, we'll use canHandleContent to find any handler + // for the content. + // We always start with the original content listener (if any) that originated the request + // and then move on to registered content listeners. + + // if we cannot find a registered content lister to handle the type, then we move on to + // phase II which is to try to find a content handler in the registry for the content type. + nsresult rv = NS_OK; nsCOMPtr listenerToUse = aContentListener; + // find a content handler that can and will handle the content - PRBool canHandleContent = PR_FALSE; + PRBool foundContentHandler = PR_FALSE; if (listenerToUse) - listenerToUse->CanHandleContent(aContentType, aCommand, aWindowTarget, - aContentTypeToUse, - &canHandleContent); - if (!canHandleContent) // if it can't handle the content, scan through the list of registered listeners + foundContentHandler = ShouldHandleContent(listenerToUse, aContentType, + aCommand, aWindowTarget, aContentTypeToUse); + + + if (!foundContentHandler) // if it can't handle the content, scan through the list of registered listeners { PRInt32 i = 0; - // keep looping until we are told to abort or we get a content listener back - for(i = 0; i < m_listeners->Count() && !canHandleContent; i++) + // keep looping until we get a content listener back + for(i = 0; i < m_listeners->Count() && !foundContentHandler; i++) { //nsIURIContentListener's aren't refcounted. nsIURIContentListener * listener =(nsIURIContentListener*)m_listeners->ElementAt(i); if (listener) - { - rv = listener->CanHandleContent(aContentType, aCommand, aWindowTarget, - aContentTypeToUse, - &canHandleContent); - if (canHandleContent) + { + foundContentHandler = ShouldHandleContent(listener, aContentType, + aCommand, aWindowTarget, aContentTypeToUse); + if (foundContentHandler) listenerToUse = listener; - } + } } // for loop } // if we can't handle the content - if (canHandleContent && listenerToUse) + if (foundContentHandler && listenerToUse) { *aContentListenerToUse = listenerToUse; NS_IF_ADDREF(*aContentListenerToUse); @@ -636,8 +667,8 @@ nsresult nsURILoader::DispatchContent(const char * aContentType, rv = nsComponentManager::CreateInstance(handlerProgID, nsnull, NS_GET_IID(nsIContentHandler), getter_AddRefs(aContentHandler)); if (NS_SUCCEEDED(rv)) // we did indeed have a content handler for this type!! yippee... { - rv = aContentHandler->HandleContent(aContentType, "view", aWindowTarget, aChannel); - *aAbortProcess = PR_TRUE; + rv = aContentHandler->HandleContent(aContentType, "view", aWindowTarget, aChannel); + *aAbortProcess = PR_TRUE; } return rv; diff --git a/mozilla/uriloader/base/nsURILoader.h b/mozilla/uriloader/base/nsURILoader.h index 4858d3e4e94..4df1c7f3956 100644 --- a/mozilla/uriloader/base/nsURILoader.h +++ b/mozilla/uriloader/base/nsURILoader.h @@ -46,6 +46,13 @@ protected: // prepare the load cookie for the window context nsresult SetupLoadCookie(nsISupports * aWindowContext, nsISupports ** aLoadCookie); + + // a small helper function + PRBool ShouldHandleContent(nsIURIContentListener * aCntListener, + const char * aContentType, + nsURILoadCommand aCommand, + const char * aWindowTarget, + char ** aContentTypeToUse); }; #endif /* nsURILoader_h__ */