PROTOCOL HANDLER
in Gecko
Tommy Kuo [:KuoE0]
kuoe0@mozilla.com
2015.03.03 @Mozilla Taiwan
Outline
• What Protocol Handlers Can Do
• The Walkthrough from Awesome Bar to Protocol
Handlers
• The Brief Introduction to Channels
What Protocol Handlers
Can Do
URI Syntax
<scheme name> : <hierarchical part> [ ? <query> ] [ # <fragment> ]
http : //google.com/search ? q=Mozilla
https : //www.facebook.com/pages/郝神好神/871866229523862
file : ///Downloads/郝神好帥.jpg
about : config
mailto : kuoe0@mozilla.com
chrome : //browser/skin/Info.png
line : //shop/detail/xxx
Protocol Handler
Format the URI Create the channel Get flags
NewChannel2(…)
NewProxiedChannel2(…)
NewURI(…) GetProtocolFlags(…)
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)
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)
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)
Create An Protocol Handler
• Implementation
• NewURI
• NewChannel2 / NewChannel (not recommended)
• GetProtocolFlags
• Registration
• See 謀智菜逼⼋八談 XPCOM 實務⼊入⾨門
./extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MOZ_GNOMEVFS_SCHEME,
&kNS_GNOMEVFSPROTOCOLHANDLER_CID },
./extensions/gio/nsGIOProtocolHandler.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MOZ_GIO_SCHEME,
&kNS_GIOPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "file", &kNS_FILEPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &kNS_HTTPPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "https", &kNS_HTTPSPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ftp", &kNS_FTPPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "resource", &kNS_RESPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "about", &kNS_ABOUTPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-safe-about",
&kNS_SAFEABOUTPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "app", &kNS_APPPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "data", &kNS_DATAPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-device",
&kNS_DEVICEPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "view-source",
&kNS_VIEWSOURCEHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "wyciwyg",
&kNS_WYCIWYGPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ws", &kNS_WEBSOCKETPROTOCOLHANDLER_CID },
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "wss", &kNS_WEBSOCKETSSLPROTOCOLHANDLER_CID
},
./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "rtsp", &kNS_RTSPPROTOCOLHANDLER_CID },
./image/decoders/icon/nsIconModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-icon", &kNS_ICONPROTOCOL_CID },
./xpcom/build/XPCOMInit.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", &kNS_CHROMEPROTOCOLHANDLER_CID },
./toolkit/components/places/nsPlacesModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-anno",
&kNS_ANNOPROTOCOLHANDLER_CID },
./widget/android/nsWidgetFactory.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "android",
&kNS_ANDROIDPROTOCOLHANDLER_CID },
./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME,
&kNS_BLOBPROTOCOLHANDLER_CID },
./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME,
&kNS_MEDIASTREAMPROTOCOLHANDLER_CID },
./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASOURCEURI_SCHEME,
&kNS_MEDIASOURCEPROTOCOLHANDLER_CID },
./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX FONTTABLEURI_SCHEME,
&kNS_FONTTABLEPROTOCOLHANDLER_CID },
./modules/libjar/nsJARFactory.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar", &kNS_JARPROTOCOLHANDLER_CID },
$ grep -ir -E "{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX [^,]+,[^}]+ }" .
Awesome Bar to
Protocol Handlers
http://google.com/
http://google.com/
How to interact to HTTP protocol?
handleCommand
openUILinkIn
openLinkIn
loadURIWithFlags (tabbrowser)
loadURIWithFlags (browser)
LoadURI(char16_t*, …)
LoadURIWithBase
LoadURI(nsIURI*, …)
InternalLoad
DoURILoad
DoChannelLoad
NS_NewURI
NS_NewChannelInternal
Browser UI
(XUL)
DocShell Necko
GetProtocolHandler
GetProtocolHandler
nsIURI
nsIChannel
NewURI
NewChannel2
Browser UI
<textbox id=“urlbar"></text>
browser/base/content/browser.xul
<tabbrowser />
<textbox id="urlbar" flex="1"
placeholder="&urlbar.placeholder2;"
type="autocomplete"
autocompletesearch="urlinline history"
autocompletesearchparam="enable-actions"
autocompletepopup="PopupAutoCompleteRichResult"
completeselectedindex="true"
tabscrolling="true"
showcommentcolumn="true"
showimagecolumn="true"
enablehistory="true"
maxrows="6"
newlines="stripsurroundingwhitespace"
ontextentered="this.handleCommand(param);"
ontextreverted="return this.handleRevert();"
pageproxystate="invalid"
onfocus="document.getElementById('identity-
box').style.MozUserFocus= 'normal'"
onblur="setTimeout(() =>
{ document.getElementById('identity-box').style.MozUserFocus = ''; }, 0);”>
. . . . . .
</textbox>
browser/base/content/urlbarBindings.xml
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)
openUILinkIn
1. Set parameters
• third-party fix-up permission
• post data
• referrer URI
2. Call openLinkIn
browser/base/content/utilityOverlay.js
openLinkIn
1. Set target to open URI
• current tab
• new tab
• new window
2. Call loadURIWithFlags (tabbrowser)
browser/base/content/utilityOverlay.js
loadURIWithFlags (tabbrowser)
1. Call loadURIWithFlags of its member browser
object
browser/base/content/tabbrowser.xml
loadURIWithFlags (browser)
1. Set “about:blank” for empty URI
2. Call loadURI
• Call nsDocShell::LoadURI actually
source/toolkit/content/widgets/browser.xml
DocShell
LoadURI(char16_t*, …)
1. Call LoadURIWithBase
docshell/base/nsDocShell.cpp
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
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
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
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
Necko
NS_NewURI NS_NewChannelInternal (7 parameter)
nsIOService::NewURI
GetProtocolHandler
NS_NewChannelInternal (11 parameter)
NewChannelFromURI2
NewChannelFromURIWithProxyFlagsInternal
GetProtocolHandler
DoURILoadLoadURIWithBase
Call Stack
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.
The Brief Introduction to
Channels
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.
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.
nsDocShell::DoChannelLoad
nsURILoader::OpenURI nsDocumentOpenInfo
nsIChannel::AsyncOpen
nsIChannel
create
call
call
nsIAsyncInputStream
create
nsInputStreamPump::AsyncRead
call
nsDocShell
nsIChannel
nsIAsyncStream
listen by nsDocmentOpenInfo
listen by self (nsIChannel)
nsDocShell nsIChannel nsIAsyncStream
OnStartRequest
OnDataAvailable
OnStopRequest
OnStartRequest
OnDataAvailable
OnStopRequest
Read
Thank you!

Protocol handler in Gecko

  • 1.
    PROTOCOL HANDLER in Gecko TommyKuo [:KuoE0] kuoe0@mozilla.com 2015.03.03 @Mozilla Taiwan
  • 2.
    Outline • What ProtocolHandlers Can Do • The Walkthrough from Awesome Bar to Protocol Handlers • The Brief Introduction to Channels
  • 3.
  • 4.
    URI Syntax <scheme name>: <hierarchical part> [ ? <query> ] [ # <fragment> ] http : //google.com/search ? q=Mozilla https : //www.facebook.com/pages/郝神好神/871866229523862 file : ///Downloads/郝神好帥.jpg about : config mailto : kuoe0@mozilla.com chrome : //browser/skin/Info.png line : //shop/detail/xxx
  • 5.
    Protocol Handler Format theURI 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)
  • 9.
    Create An ProtocolHandler • Implementation • NewURI • NewChannel2 / NewChannel (not recommended) • GetProtocolFlags • Registration • See 謀智菜逼⼋八談 XPCOM 實務⼊入⾨門
  • 10.
    ./extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIXMOZ_GNOMEVFS_SCHEME, &kNS_GNOMEVFSPROTOCOLHANDLER_CID }, ./extensions/gio/nsGIOProtocolHandler.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MOZ_GIO_SCHEME, &kNS_GIOPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "file", &kNS_FILEPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &kNS_HTTPPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "https", &kNS_HTTPSPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ftp", &kNS_FTPPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "resource", &kNS_RESPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "about", &kNS_ABOUTPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-safe-about", &kNS_SAFEABOUTPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "app", &kNS_APPPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "data", &kNS_DATAPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-device", &kNS_DEVICEPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "view-source", &kNS_VIEWSOURCEHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "wyciwyg", &kNS_WYCIWYGPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "ws", &kNS_WEBSOCKETPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "wss", &kNS_WEBSOCKETSSLPROTOCOLHANDLER_CID }, ./netwerk/build/nsNetModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "rtsp", &kNS_RTSPPROTOCOLHANDLER_CID }, ./image/decoders/icon/nsIconModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-icon", &kNS_ICONPROTOCOL_CID }, ./xpcom/build/XPCOMInit.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "chrome", &kNS_CHROMEPROTOCOLHANDLER_CID }, ./toolkit/components/places/nsPlacesModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-anno", &kNS_ANNOPROTOCOLHANDLER_CID }, ./widget/android/nsWidgetFactory.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "android", &kNS_ANDROIDPROTOCOLHANDLER_CID }, ./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX BLOBURI_SCHEME, &kNS_BLOBPROTOCOLHANDLER_CID }, ./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASTREAMURI_SCHEME, &kNS_MEDIASTREAMPROTOCOLHANDLER_CID }, ./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MEDIASOURCEURI_SCHEME, &kNS_MEDIASOURCEPROTOCOLHANDLER_CID }, ./layout/build/nsLayoutModule.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX FONTTABLEURI_SCHEME, &kNS_FONTTABLEPROTOCOLHANDLER_CID }, ./modules/libjar/nsJARFactory.cpp: { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar", &kNS_JARPROTOCOLHANDLER_CID }, $ grep -ir -E "{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX [^,]+,[^}]+ }" .
  • 11.
  • 13.
  • 14.
  • 15.
    handleCommand openUILinkIn openLinkIn loadURIWithFlags (tabbrowser) loadURIWithFlags (browser) LoadURI(char16_t*,…) LoadURIWithBase LoadURI(nsIURI*, …) InternalLoad DoURILoad DoChannelLoad NS_NewURI NS_NewChannelInternal Browser UI (XUL) DocShell Necko GetProtocolHandler GetProtocolHandler nsIURI nsIChannel NewURI NewChannel2
  • 16.
  • 17.
  • 18.
    <textbox id="urlbar" flex="1" placeholder="&urlbar.placeholder2;" type="autocomplete" autocompletesearch="urlinlinehistory" autocompletesearchparam="enable-actions" autocompletepopup="PopupAutoCompleteRichResult" completeselectedindex="true" tabscrolling="true" showcommentcolumn="true" showimagecolumn="true" enablehistory="true" maxrows="6" newlines="stripsurroundingwhitespace" ontextentered="this.handleCommand(param);" ontextreverted="return this.handleRevert();" pageproxystate="invalid" onfocus="document.getElementById('identity- box').style.MozUserFocus= 'normal'" onblur="setTimeout(() => { document.getElementById('identity-box').style.MozUserFocus = ''; }, 0);”> . . . . . . </textbox> browser/base/content/urlbarBindings.xml
  • 19.
    handleCommand 1.Canonize URI 2.Detect targetin 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 targetto open URI • current tab • new tab • new window 2. Call loadURIWithFlags (tabbrowser) browser/base/content/utilityOverlay.js
  • 22.
    loadURIWithFlags (tabbrowser) 1. CallloadURIWithFlags of its member browser object browser/base/content/tabbrowser.xml
  • 23.
    loadURIWithFlags (browser) 1. Set“about:blank” for empty URI 2. Call loadURI • Call nsDocShell::LoadURI actually source/toolkit/content/widgets/browser.xml
  • 24.
  • 25.
    LoadURI(char16_t*, …) 1. CallLoadURIWithBase docshell/base/nsDocShell.cpp
  • 26.
    LoadURIWithBase 1. Check navigatableor 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. Checknavigatable 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 contentpolicy 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 isnot 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
  • 30.
  • 31.
    NS_NewURI NS_NewChannelInternal (7parameter) nsIOService::NewURI GetProtocolHandler NS_NewChannelInternal (11 parameter) NewChannelFromURI2 NewChannelFromURIWithProxyFlagsInternal GetProtocolHandler DoURILoadLoadURIWithBase Call Stack
  • 32.
    GetProtocolHandler 1.Return protocol handlerif 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.
  • 34.
  • 35.
    Channel (nsIChannel) AsyncOpen() (Non-blockingIO) 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 tosignify 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.
  • 37.
  • 38.
  • 39.
  • 40.