5. Protocol Handler
Format the URI Create the channel Get flags
NewChannel2(…)
NewProxiedChannel2(…)
NewURI(…) GetProtocolFlags(…)
6. nsresult
nsIOService::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI,
nsIURI **result)
{
NS_ASSERTION(NS_IsMainThread(), "wrong thread");
static uint32_t recursionCount = 0;
if (recursionCount >= MAX_RECURSION_COUNT)
return NS_ERROR_MALFORMED_URI;
AutoIncrement inc(&recursionCount);
nsAutoCString scheme;
nsresult rv = ExtractScheme(aSpec, scheme);
if (NS_FAILED(rv)) {
// then aSpec is relative
if (!aBaseURI)
return NS_ERROR_MALFORMED_URI;
rv = aBaseURI->GetScheme(scheme);
if (NS_FAILED(rv)) return rv;
}
// now get the handler for this scheme
nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
if (NS_FAILED(rv)) return rv;
return handler->NewURI(aSpec, aCharset, aBaseURI, result);
}
nsIOService::NewURI
(netwerk/base/nsIOService.cpp)
7. nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
if (NS_FAILED(rv))
return rv;
uint32_t protoFlags;
rv = handler->GetProtocolFlags(&protoFlags);
if (NS_FAILED(rv))
return rv;
bool newChannel2Succeeded = true;
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
if (pph) {
rv = pph->NewProxiedChannel2(aURI, nullptr, aProxyFlags, aProxyURI, aLoadInfo, result);
// if calling NewProxiedChannel2() fails we try to fall back to
// creating a new proxied channel by calling NewProxiedChannel().
if (NS_FAILED(rv)) {
newChannel2Succeeded = false;
rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI, result);
}
}
else {
rv = handler->NewChannel2(aURI, aLoadInfo, result);
// if calling newChannel2() fails we try to fall back to
// creating a new channel by calling NewChannel().
if (NS_FAILED(rv)) {
newChannel2Succeeded = false;
rv = handler->NewChannel(aURI, result);
}
}
nsIOService::NewChannelFromURIWithProxyFlagsInternal
(netwerk/base/nsIOService.cpp)
8. nsCOMPtr<nsIProtocolHandler> handler;
rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
if (NS_FAILED(rv))
return rv;
uint32_t protoFlags;
rv = handler->GetProtocolFlags(&protoFlags);
if (NS_FAILED(rv))
return rv;
bool newChannel2Succeeded = true;
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
if (pph) {
rv = pph->NewProxiedChannel2(aURI, nullptr, aProxyFlags, aProxyURI, aLoadInfo, result);
// if calling NewProxiedChannel2() fails we try to fall back to
// creating a new proxied channel by calling NewProxiedChannel().
if (NS_FAILED(rv)) {
newChannel2Succeeded = false;
rv = pph->NewProxiedChannel(aURI, nullptr, aProxyFlags, aProxyURI, result);
}
}
else {
rv = handler->NewChannel2(aURI, aLoadInfo, result);
// if calling newChannel2() fails we try to fall back to
// creating a new channel by calling NewChannel().
if (NS_FAILED(rv)) {
newChannel2Succeeded = false;
rv = handler->NewChannel(aURI, result);
}
}
nsIOService::NewChannelFromURIWithProxyFlagsInternal
(netwerk/base/nsIOService.cpp)
19. handleCommand
1.Canonize URI
2.Detect target in the current tab or a new tab
3.Call openUILinkIn
browser/base/content/urlbarBindings.xml
google mozilla https://www.google.com.tw/search?q=mozilla search engine
tv http://tv.atmovies.com.tw/tv/attv.cfm?action=todaytime bookmark keyword
google http://www.google.com
hotkey
(Ctrl/Cmd+Enter)
google http://www.google.net
hotkey
(Shift+Enter)
20. openUILinkIn
1. Set parameters
• third-party fix-up permission
• post data
• referrer URI
2. Call openLinkIn
browser/base/content/utilityOverlay.js
21. openLinkIn
1. Set target to open URI
• current tab
• new tab
• new window
2. Call loadURIWithFlags (tabbrowser)
browser/base/content/utilityOverlay.js
26. LoadURIWithBase
1. Check navigatable or not
2. Call NS_NewURI to create an instance of nsIURI
3. Fix up URI if allowed
4. Call LoadURI
docshell/base/nsDocShell.cpp
ttp → http
ps → https
le → file
27. LoadURI(nsIURI*, …)
1. Check navigatable or not
2. Redirect if needed
3. Call LoadHistoryEntry to load from history if
shEntry exists
4. Call InternalLoad
docshell/base/nsDocShell.cpp
session history
28. InternalLoad
1. Get content policy
2. Decide to load or not according to the content policy
3. Do shortcut loading if only hash tags are different
4. Call DoURILoad
docshell/base/nsDocShell.cpp
29. DoURILoad
1. URI is not a source document
• Call NS_NewChannelInternal to create channel
2. URI is a source document
• Get “view-source” channel if protocol is “view-source”
• Call NS_NewInputStreamChannelInternal to create
channel for “text/html”
3. Setup some data for specific protocols
4. Call DoChannelLoad to load channel
docshell/base/nsDocShell.cpp
32. GetProtocolHandler
1.Return protocol handler if the protocol handler was
cached
2.For internal protocol
• Cache the protocol handler and return
3.For external protocol
• Get default external protocol handler for external
protocol
netwerk/base/nsIOService.cpp
Protocols are not provided in gecko.
35. Channel (nsIChannel)
AsyncOpen() (Non-blocking IO)
Asynchronously open this channel. Data is fed to the
specified stream listener as it becomes available.
Open() (Blocking IO)
Synchronously open the channel.
36. Listener (nsIStreamListener)
OnStartRequest()
Called to signify the beginning of an asynchronous request.
OnStopRequest()
Called to signify the end of an asynchronous request.
OnDataAvailable()
Called when the next chunk of data may be read without
blocking the calling thread.