<commit_before>/*
 * @author: <NAME>
 * See COPYING for copyright and distribution information.
 * This is the ndn protocol handler.
 * Protocol handling code derived from http://mike.kaply.com/2011/01/18/writing-a-firefox-protocol-handler/
 */

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const nsIProtocolHandler = Ci.nsIProtocolHandler;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("chrome://modules/content/ndn-js.jsm");
Components.utils.import("chrome://modules/content/ContentChannel.jsm");

function NdnProtocol() {
}

NdnProtocol.prototype = {
    scheme: "ndn",
    protocolFlags: nsIProtocolHandler.URI_NORELATIVE |
                   nsIProtocolHandler.URI_NOAUTH |
                   nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,
    transport: new XpcomTransport(),

    newURI: function(aSpec, aOriginCharset, aBaseURI)
    {
        // We have to trim now because nsIURI converts spaces to %20 and we can't trim in newChannel.
        var spec = aSpec.trim();
        var preSearch = spec.split('?', 1)[0];
        var searchAndHash = spec.substr(preSearch.length).trim();

        var uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
        uri.spec = preSearch.trim() + searchAndHash;
        return uri;
    },

    newChannel: function(aURI)
    {
        var thisNdnProtocol = this;
        
        try {            
            // Decode manually since nsIURI doesn't have selectors for hash, etc.
            var spec = aURI.spec.trim();
            var preHash = spec.split('#', 1)[0];
            var hash = spec.substr(preHash.length).trim();
            var preSearch = preHash.split('?', 1)[0];
            var search = preHash.substr(preSearch.length).trim();
            // Set nameString to the preSearch without the protocol.
            var nameString = preSearch.trim();
            if (nameString.indexOf(':') >= 0)
                nameString = nameString.substr(nameString.indexOf(':') + 1).trim();
    
            var template = new Interest(new Name([]));
            // Use the same default as NDN.expressInterest.
            template.interestLifetime = 4200;
            var searchWithoutNdn = extractNdnSearch(search, template);
    
            var requestContent = function(contentListener) {                
                var name = new Name(nameString);
                // TODO: Strip off an ending implicit digest before checking the last component?
                var uriEndsWithSegmentNumber = endsWithSegmentNumber(name);
                
                var ndn = new NDN({ host: "lioncub.metwi.ucla.edu", port: 9695,
                      // Use the same transport object each time.
                      getTransport: function() { return thisNdnProtocol.transport; } });
                ndn.expressInterest(name, 
                    new ContentClosure(ndn, contentListener, uriEndsWithSegmentNumber, 
                            aURI.originCharset, searchWithoutNdn + hash),
                    template);
            };

            return new ContentChannel(aURI, requestContent);
        } catch (ex) {
            dump("NdnProtocol.newChannel exception: " + ex + "\n" + ex.stack);
        }
    },

    classDescription: "ndn Protocol Handler",
    contractID: "@mozilla.org/network/protocol;1?name=" + "ndn",
    classID: Components.ID('{8122e660-1012-11e2-892e-0800200c9a66}'),
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
}

if (XPCOMUtils.generateNSGetFactory)
    var NSGetFactory = XPCOMUtils.generateNSGetFactory([NdnProtocol]);
else
    var NSGetModule = XPCOMUtils.generateNSGetModule([NdnProtocol]);
                
/*
 * Create a closure for calling expressInterest.
 * contentListener is from the call to requestContent.
 * uriEndsWithSegmentNumber is true if the URI passed to newChannel has a segment number
 *    (used to determine whether to request only that segment number and for updating the URL bar).
 * uriOriginCharset is the charset of the URI passed to newChannel (used for making a new URI)
 * uriSearchAndHash is the search and hash part of the URI passed to newChannel, including the '?'
 *    and/or '#' but without the interest selector fields.
 */                                                
var ContentClosure = function ContentClosure
        (ndn, contentListener, uriEndsWithSegmentNumber, uriOriginCharset, uriSearchAndHash) {
    // Inherit from Closure.
    Closure.call(this);
    
    this.ndn = ndn;
    this.contentListener = contentListener;
    this.uriEndsWithSegmentNumber = uriEndsWithSegmentNumber;
    this.uriOriginCharset = uriOriginCharset;
    this.uriSearchAndHash = uriSearchAndHash;
    
    this.firstReceivedSegmentNumber = null;
    this.firstReceivedContentObject = null;
    this.contentSha256 = null;
}

ContentClosure.prototype.upcall = function(kind, upcallInfo) {
    if (!(kind == Closure.UPCALL_CONTENT ||
          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
        // The upcall is not for us.
        return Closure.RESULT_ERR;
        
    var contentObject = upcallInfo.contentObject;
    if (contentObject.content == null) {
        dump("NdnProtocol.ContentClosure: contentObject.content is null\n");
        return Closure.RESULT_ERR;
    }

    // If !this.uriEndsWithSegmentNumber, we use the segmentNumber to load multiple segments.
    var segmentNumber = null;
    if (!this.uriEndsWithSegmentNumber && endsWithSegmentNumber(contentObject.name)) {
        segmentNumber = DataUtils.bigEndianToUnsignedInt<commit_msg>Create and keep one NDN object.  Allow it to use XpcomTransport.defaultGetHostAndPort to select a testbed host at random.<commit_after>/*
 * @author: <NAME>
 * See COPYING for copyright and distribution information.
 * This is the ndn protocol handler.
 * Protocol handling code derived from http://mike.kaply.com/2011/01/18/writing-a-firefox-protocol-handler/
 */

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;

const nsIProtocolHandler = Ci.nsIProtocolHandler;

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("chrome://modules/content/ndn-js.jsm");
Components.utils.import("chrome://modules/content/ContentChannel.jsm");

function NdnProtocol() {
    this.ndn = new NDN({ getTransport: function() { return new XpcomTransport(); } });
    this.ndn.host = null; // TODO: Remove this when null is the default.
}

NdnProtocol.prototype = {
    scheme: "ndn",
    protocolFlags: nsIProtocolHandler.URI_NORELATIVE |
                   nsIProtocolHandler.URI_NOAUTH |
                   nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,

    newURI: function(aSpec, aOriginCharset, aBaseURI)
    {
        // We have to trim now because nsIURI converts spaces to %20 and we can't trim in newChannel.
        var spec = aSpec.trim();
        var preSearch = spec.split('?', 1)[0];
        var searchAndHash = spec.substr(preSearch.length).trim();

        var uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
        uri.spec = preSearch.trim() + searchAndHash;
        return uri;
    },

    newChannel: function(aURI)
    {
        var thisNdnProtocol = this;
        
        try {            
            // Decode manually since nsIURI doesn't have selectors for hash, etc.
            var spec = aURI.spec.trim();
            var preHash = spec.split('#', 1)[0];
            var hash = spec.substr(preHash.length).trim();
            var preSearch = preHash.split('?', 1)[0];
            var search = preHash.substr(preSearch.length).trim();
            // Set nameString to the preSearch without the protocol.
            var nameString = preSearch.trim();
            if (nameString.indexOf(':') >= 0)
                nameString = nameString.substr(nameString.indexOf(':') + 1).trim();
    
            var template = new Interest(new Name([]));
            // Use the same default as NDN.expressInterest.
            template.interestLifetime = 4.0;
            var searchWithoutNdn = extractNdnSearch(search, template);
    
            var requestContent = function(contentListener) {                
                var name = new Name(nameString);
                // TODO: Strip off an ending implicit digest before checking the last component?
                var uriEndsWithSegmentNumber = endsWithSegmentNumber(name);
                
                // Use the same NDN object each time.
                thisNdnProtocol.ndn.expressInterest(name, 
                    new ContentClosure(thisNdnProtocol.ndn, contentListener, uriEndsWithSegmentNumber, 
                            aURI.originCharset, searchWithoutNdn + hash),
                    template);
            };

            return new ContentChannel(aURI, requestContent);
        } catch (ex) {
            dump("NdnProtocol.newChannel exception: " + ex + "\n" + ex.stack);
        }
    },

    classDescription: "ndn Protocol Handler",
    contractID: "@mozilla.org/network/protocol;1?name=" + "ndn",
    classID: Components.ID('{8122e660-1012-11e2-892e-0800200c9a66}'),
    QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler])
};

if (XPCOMUtils.generateNSGetFactory)
    var NSGetFactory = XPCOMUtils.generateNSGetFactory([NdnProtocol]);
else
    var NSGetModule = XPCOMUtils.generateNSGetModule([NdnProtocol]);
                
/*
 * Create a closure for calling expressInterest.
 * contentListener is from the call to requestContent.
 * uriEndsWithSegmentNumber is true if the URI passed to newChannel has a segment number
 *    (used to determine whether to request only that segment number and for updating the URL bar).
 * uriOriginCharset is the charset of the URI passed to newChannel (used for making a new URI)
 * uriSearchAndHash is the search and hash part of the URI passed to newChannel, including the '?'
 *    and/or '#' but without the interest selector fields.
 */                                                
var ContentClosure = function ContentClosure
        (ndn, contentListener, uriEndsWithSegmentNumber, uriOriginCharset, uriSearchAndHash) {
    // Inherit from Closure.
    Closure.call(this);
    
    this.ndn = ndn;
    this.contentListener = contentListener;
    this.uriEndsWithSegmentNumber = uriEndsWithSegmentNumber;
    this.uriOriginCharset = uriOriginCharset;
    this.uriSearchAndHash = uriSearchAndHash;
    
    this.firstReceivedSegmentNumber = null;
    this.firstReceivedContentObject = null;
    this.contentSha256 = null;
};

ContentClosure.prototype.upcall = function(kind, upcallInfo) {
    if (!(kind == Closure.UPCALL_CONTENT ||
          kind == Closure.UPCALL_CONTENT_UNVERIFIED))
        // The upcall is not for us.
        return Closure.RESULT_ERR;
        
    var contentObject = upcallInfo.contentObject;
    if (contentObject.content == null) {
        dump("NdnProtocol.ContentClosure: contentObject.content is null\n");
        return Closure.RESULT_ERR;
    }

    // If !this.uriEndsWithSegmentNumber, we use the segmentNumber to load multiple segments.
    var segmentNumber = null;
    if (!this.uriEndsWithSegmentNumber && endsWithSegmentNumber(contentObject.name)) {
        segmentNumber = DataUtils.bigEndianToUnsignedInt
{'fraction_non_alphanumeric': 0.09763654067451535, 'fraction_numerical': 0.009737098344693282, 'mean_word_length': 2.639819587628866, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5099719', 'n_tokens_mistral': 3228, 'n_tokens_neox': 3096, 'n_words': 801}