Gupshup - multiple messages delay feature not working - gupshup

I've tried to implement a delay feature on my bot to display multiple messages one after the other. The delay feature is displaying in my Flow Bot Builder diagram, but when I test in the conversation tester, and proxy bot on Messenger, the delay doesn't actually happen - all the messages display at once.
I have added the delay code in the IDE to the default.scr file:
[main]
label_dych:Hi! I'm delay-bot and I'm here to help you with any questions you have.:continue
((delay 2000))
label_gthk:I'll never need to take any personal or financial information from you, so as we chat please don't tell me any!:continue
((delay 1000))
label_ylbn:{"name":"quickreply","type":"quick_reply","alias":"What can I help you with?","msgid":"117af569-5188-ff7e-9b48-8c553c2f36cb","content":{"type":"text","text":"What can I help you with?"},"options":[{"type":"text","title":"My Page","iconurl":"","id":"ac49ad32-c9bc-469f-2152-c7c842bad8ea","isDuplicate":false,"name":"user"},{"type":"text","title":"Team Spaces","iconurl":"","id":"8a2017ac-2fc3-0901-be8d-1fad5a2dba12","isDuplicate":false,"name":"user"},{"type":"text","title":"Offline Support","iconurl":"","id":"70861407-e706-17a3-207b-c43958fde83e","isDuplicate":false,"name":"user"},{"type":"text","title":"Something else","iconurl":"","id":"d3f7b6b4-e70a-098d-dde9-1da3e8cc08dc","isDuplicate":false,"name":"user"}]}
I've also added the options.apikey line of code to the index.js file as instructed to do here: https://www.gupshup.io/developer/docs/bot-platform/guide/sending-multiple-messages-botscript
function ScriptHandler(context, event){
var options = Object.assign({}, scr_config);
options.current_dir = __dirname;
//options.default_message = "Sorry Some Error Occurred.";
// You can add any start point by just mentioning the
<script_file_name>.<section_name>
// options.start_section = "default.main";
options.success = function(opm){
context.sendResponse(JSON.stringify(opm));
};
options.error = function(err) {
console.log(err.stack);
context.sendResponse(options.default_message);
};
botScriptExecutor.execute(options, event, context);
options.apikey = "1mbccef47ab24dacad3f99557cb35643";
}
Is there any obvious reason why the delay effect wouldn't be working in between messages? I've used the apikey that is displayed for my gupshup account when I click the logo in the top right.

You have placed the API key after the scripting tool execute function is called. Place the API Key anywhere before the botScriptExecutor.execute and the delay should work.
Also, the timing of the delay is in milliseconds.
Sample:
function ScriptHandler(context, event){
var options = Object.assign({}, scr_config);
options.current_dir = __dirname;
//options.default_message = "Sorry Some Error Occurred.";
options.apikey = "1mbccef47ab24dacad3f99557cb35643";
// You can add any start point by just mentioning the
<script_file_name>.<section_name>
// options.start_section = "default.main";
options.success = function(opm){
context.sendResponse(JSON.stringify(opm));
};
options.error = function(err) {
console.log(err.stack);
context.sendResponse(options.default_message);
};
botScriptExecutor.execute(options, event, context);
}

Related

Unable to get Twilio sms status callbacks when sending proactive message

I'm trying to track the sms delivery status of the messages I send using the bot framework. I'm using Twilio, and sending proactive messages. Right now I'm trying to do so with twilio status callbacks
This is similar to this question, I tried that approach but I couldn't get it to work. I've added my url on the TwiML app and it is not firing. I have double and triple checked, and I suspect this url is somehow ignored or not going through with my current set up. I don't get any callbacks on the proactive message nor on the replies the bot sends to the user. However the flow works fine and I can reply and get proper responses from the bot. Edit: calling this "approach 1"
approach 2: I've also tried this doing some light modifications on Twilio adapter, to be able to add my callback just before create message. (I changed it so it uses a customized client wrapper that adds my callback url when creating the twilio resource) This does work, partially: when I reply a message from my bot, I get the status callbacks. But as the proactive message is sent using the default adapter, I don't get a callback on the initial message.
approach 3: Finally, I also tried using the TwilioAdapter when sending the proactive message but for some reason as soon as I send an activity, the TurnContext is disposed, so I can't save the state or do any subsequent actions. This leads me to believe twilio adapter is not intended to be used this way (can't be used on proactive messages), but I'm willing to explore this path if necessary.
Here is the modified Twilio Adapter:
public class TwilioAdapterWithErrorHandler : TwilioAdapter
{
private const string TwilioNumberKey = "TwilioNumber";
private const string TwilioAccountSidKey = "TwilioAccountSid";
private const string TwilioAuthTokenKey = "TwilioAuthToken";
private const string TwilioValidationUrlKey = "TwilioValidationUrl";
public TwilioAdapterWithErrorHandler(IConfiguration configuration, ILogger<TwilioAdapter> logger, TwilioAdapterOptions adapterOptions = null)
: base(
new TwilioClientWrapperWithCallback(new TwilioClientWrapperOptions(configuration[TwilioNumberKey], configuration[TwilioAccountSidKey], configuration[TwilioAuthTokenKey], new Uri(configuration[TwilioValidationUrlKey]))), adapterOptions, logger)
{
OnTurnError = async (turnContext, exception) =>
{
// Log any leaked exception from the application.
logger.LogError(exception, $"[OnTurnError] unhandled error : {exception.Message}");
Task[] tasks = {
// Send a message to the user
turnContext.SendActivityAsync("We're sorry but this bot encountered an error when processing your answer."),
// Send a trace activity, which will be displayed in the Bot Framework Emulator
turnContext.TraceActivityAsync("OnTurnError Trace", exception.Message, "https://www.botframework.com/schemas/error", "TurnError")
};
Task all = Task.WhenAll(tasks); //task with the long running tasks
await Task.WhenAny(all, Task.Delay(5000)); //wait with a timeout
};
}
}
Modified client Wrapper:
public class TwilioClientWrapperWithCallback : TwilioClientWrapper
{
public TwilioClientWrapperWithCallback(TwilioClientWrapperOptions options) : base(options) { }
public async override Task<string> SendMessageAsync(TwilioMessageOptions messageOptions, CancellationToken cancellationToken)
{
var createMessageOptions = new CreateMessageOptions(messageOptions.To)
{
ApplicationSid = messageOptions.ApplicationSid,
MediaUrl = messageOptions.MediaUrl,
Body = messageOptions.Body,
From = messageOptions.From,
};
createMessageOptions.StatusCallback = new System.Uri("https://myApp.ngrok.io/api/TwilioSms/SmsStatusUpdated");
var messageResource = await MessageResource.CreateAsync(createMessageOptions).ConfigureAwait(false);
return messageResource.Sid;
}
}
Finally, here's my summarized code that sends the proactive message:
[HttpPost("StartConversationWithSuperBill/{superBillId:long}")]
[HttpPost("StartConversationWithSuperBill/{superBillId:long}/Campaign/{campaignId:int}")]
public async Task<IActionResult> StartConversation(long superBillId, int? campaignId)
{
ConversationReference conversationReference = this.GetConversationReference("+17545517768");
//Start a new conversation.
await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, async (turnContext, token) =>
{
await turnContext.SendActivityAsync("proactive message 1");
//this code was edited for brevity. Here I would start a new dialog that would cascade into another, but the end result is the same, as soon as a message is sent, the turn context is disposed.
await turnContext.SendActivityAsync("proactive message 2"); //throws ObjectDisposedException
}, default(CancellationToken));
var result = new { status = "Initialized fine!" };
return new JsonResult(result);
}
private ConversationReference GetConversationReference(string targetNumber)
{
string fromNumber = "+18632704234";
return new ConversationReference
{
User = new ChannelAccount { Id = targetNumber, Role = "user" },
Bot = new ChannelAccount { Id = fromNumber, Role = "bot" },
Conversation = new ConversationAccount { Id = targetNumber },
//ChannelId = "sms",
ChannelId = "twilio-sms", //appparently when using twilio adapter we need to set this. if using TwiML app and not using Twilio Adapter, use the above. Otherwise the frameworks interprets answers from SMS as new conversations instead.
ServiceUrl = "https://sms.botframework.com/",
};
}
(I can see that I could just call create conversation reference and do two callbacks, one for each message, but in my actual code I'm creating a dialog that sends one message and then invokes another dialog that starts another message)
Edit 2:
Some clarifications:
On approach 2, I'm using two adapters, as suggested by code sample and documentation on using twilio adapter. The controller that starts the proactive message uses an instance of a default adapter (similar to this one), and TwilioController (the one that gets the twilio incoming messages) uses TwilioAdapterWithErrorHandler.
On approach 3, I excluded the default adapter, and both controllers use TwilioAdapterWithErrorHandler.
Edit 3:
Here's a small repo with the issue.
I found a fix for this problem, around approach 3, by changing the overload I use for ContinueConversation. Replace this :
//Start a new conversation.
await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, async (turnContext, token) =>
With this:
//Start a new conversation.
var twilioAdapter = (TwilioAdapterWithErrorHandler)_adapter;
await twilioAdapter.ContinueConversationAsync(_appId, conversationReference, async (context, token) =>
This way, the context is not disposed, an I can use the twilio adapter for the proactive message and have status callbacks on all messages.

Using Google Assistant Change Firebase Database Value

I Created a android app in which if a press a button and value changes in Firebase database (0/1) , i want to do this using google assistant, please help me out, i searched out but didn't found any relevant guide please help me out
The code to do this is fairly straightforward - in your webhook fulfillment you'll need a Firebase database object, which I call fbdb below. In your Intent handler, you'll get a reference to the location you want to change and make the change.
In Javascript, this might look something like this:
app.intent('value.update', conv => {
var newValue = conv.prameters.value;
var ref = fbdb.ref('path/to/value');
return ref.set(newValue)
.then(result => {
return conv.ask(`Ok, I've set it to ${newValue}, what do you want to do now?`);
})
.catch(err => {
console.error( err );
return conv.close('I had a problem with the database. Try again later.');
});
return
});
The real problem you have is what user you want to use to do the update. You can do this with an admin-level connection, which can give you broad access beyond what your security rules allow. Consult the authentication guides and be careful.
I am actually working on a project using Dialogflow webhook and integrated Firebase database. To make this posible you have to use the fulfilment on JSON format ( you cant call firebasedatabase in the way you are doing)
Here is an example to call firebase database and display a simple text on a function.
First you have to take the variable from the json.. its something loike this (on my case, it depends on your Entity Name, in my case it was "tema")
var concepto = request.body.queryResult.parameters.tema;
and then in your function:
'Sample': () => {
db.child(variable).child("DESCRIP").once('value', snap => {
var descript = snap.val(); //firebasedata
let responseToUser = {
"fulfillmentMessages": [
{ //RESPONSE FOR WEB PLATFORM===================================
'platform': 'PLATFORM_UNSPECIFIED',
"text": {
"text": [
"Esta es una respuesta por escritura de PLATFORM_UNSPECIFIED" + descript;
]
},
}
]
}
sendResponse(responseToUser); // Send simple response to user
});
},
these are links to format your json:
Para formatear JSON:
A) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Platform
B) https://cloud.google.com/dialogflow-enterprise/docs/reference/rest/Shared.Types/Message#Text
And finally this is a sample that helped a lot!!
https://www.youtube.com/watch?v=FuKPQJoHJ_g
Nice day!
after searching out i find guide which can help on this :
we need to first create chat bot on dialogflow/ api.pi
Then need to train our bot and need to use webhook as fullfillment in
response.
Now we need to setup firebase-tools for sending reply and doing
changes in firebase database.
At last we need to integrate dialogflow with google assistant using google-actions
Here is my sample code i used :
`var admin = require('firebase-admin');
const functions = require('firebase-functions');
admin.initializeApp(functions.config().firebase);
var database = admin.database();
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
exports.hello = functions.https.onRequest((request, response) => {
let params = request.body.result.parameters;
database.ref().set(params);
response.send({
speech: "Light controlled successfully"
});
});`

Send MMS using Twilio.TwimlResponse()

I'm using a node server with a webhook for handling receiving Twilio messages to one of my numbers. I use this number to forward communications between users, essentially anonymizing things for them (they communicate with our number so they don't have to give theirs to the other user).
In my handler, I currently basically do this:
var sendTo = /* other user's number */;
var sendFrom = /* sender number in received message */;
var body = /* body of message received */;
twimlResponse(body, {
to: sendTo,
from: sendFrom
});
response.send(twimlResponse.toString());
This works perfect for text messages. However, my debug log is showing errors for media messages with no body (also not forwarding the media in general, since I'm not currently telling it to).
So, I'm trying to update to send the media messages as well. This is not working well.
I found this documentation: https://www.twilio.com/docs/guides/how-to-receive-and-reply-in-node-js#respond-with-media-mms-message
However, it doesn't work. I get an error saying 'this' has no method 'To'.
I tried modifying my code a bit,
var sendTo = /* other user's number */;
var sendFrom = /* sender number in received message */;
var body = /* body of message received */;
var mediaUrl = /* mediaUrl0 of the received message */
if( body && mediaUrl ) {
twimlResponse(body, {
to: sendTo,
from: sendFrom,
mediaUrl: mediaUrl
});
}
else if( body ) {
twimlResponse(body, {
to: sendTo,
from: sendFrom
});
}
else if( mediaUrl ) {
twimlResponse(nil, {
to: sendTo,
from: sendFrom,
mediaUrl: mediaUrl
});
}
response.send(twimlResponse.toString());
I haven't yet verified that last one is correct for sending a message with no body, but my issue is that I can't figure out how to tell the twiml response to include the media. I've tried Media, media, MediaUrl, MediaUrl0, mediaUrl0, and mediaUrl. Each time I get a warning in my debugger saying it was an invalid noun. The Twiml Documentation says the nouns should be case sensitive and capitalized, though for some reason to and from are taken lower case. That part all works fine. I just can't figure out how to attach the media url.
Any tips are appreciated!
Edit -
Here is one attempt based on the linked documentation, which I thought wasn't working at all, but re-arranging the order of properties I set, I see I'm just not setting the to / from number appropriately. I know a twiml without those passed in automatically responds to the number that sent a message, from the number that received it. I need to specify both those values since I'm forwarding one user's message to another.
twimlResp.message(function() {
this.body(body);
this.media(media0);
this.to(sendTo);
this.from(sendFrom);
});
This snippet works fine for body and media, similar to the documentation, but crashes when setting to
Edit - I've tried changing this.to and this.from to this.To and this.From, but those don't work.
I've also tried this:
twimlResp.message(function() {
this.body(body);
this.media(media0);
});
twimlResp.to = sendTo;
twimlResp.from = sendFrom;
Which also does not work - .to and .from are ignored, causing the response to go back to the sending user from the number that received the original message.
I think you've gotten confused between the 2.0 and the 3.0 SDK. You can change between SDK versions by clicking in the top right of the example screen.
With your example provided, using the 3.0 SDK you can achieve this by:
var MessagingResponse = require('twilio').twiml.MessagingResponse;
var twiml = new MessagingResponse();
// Place your constraints here
var message = twiml.message({ to: sendTo, from: sendFrom });
if( body && mediaUrl ) {
message.body(body);
message.media(mediaUrl);
}
else if( body ) {
messsage.body(body);
}
else if( mediaUrl ) {
messsage.media(mediaUrl);
}
response.send(twiml.toString());
If you need a more in-depth detail on how I formulated this code, check out the MessagingResposne.js source. I'm assuming you have no restrictions on switching SDK versions, the reason I gave an example with the 3.0 SDK is because Twilio will be ending support for the 2.0 SDK as of 8/31/2017.
Howto with SDK 2.0
Since some users will need to migrate a large part of their codebase, here is how you can set a different to and from numbers with the SDK 2.0.
twimlResp.message(function() {
this.body(body);
this.media(media0);
}, {
to: sendTo,
from: sendFrom
});

Appcelerator - Getting geolocation information and turning into a URL

I'm still very new to appcelerator but I'm trying to do a small experiment with geolocation. I have some code similar to below, which returns the long and lat to the console. What I would like to is get the long and lat and append them to a URL, e.g http://www.mywebsite.com/lat/long.
I've tried creating a simple alert to show me the current location in the but all it says is Alert: [object GeolocationModule].
Could somebody point me in the right direction so I can learn some more? Thank you
if (Ti.Geolocation.locationServicesEnabled) {
Titanium.Geolocation.purpose = 'Get Current Location';
Titanium.Geolocation.getCurrentPosition(function(e) {
if (e.error) {
Ti.API.error('Error: ' + e.error);
} else {
Ti.API.info(e.coords);
}
});
} else {
alert('Please enable location services');
}
This is how you need to follow the API documentation:
You can have a look at the LocationResults page: https://docs.appcelerator.com/platform/latest/#!/api/LocationResults which leads you to LocationCoordinates: https://docs.appcelerator.com/platform/latest/#!/api/LocationCoordinates
There you can see, that you can use e.coords.latitude or longitude to get the values. Or have a look at the console output. It should show you a JSON output with the key-value pairs.
Once you have the values you can create a HTTP request (demo: https://docs.appcelerator.com/platform/latest/#!/guide/HTTPClient_and_the_Request_Lifecycle) and open your page:
var url = "https://www.appcelerator.com/"+e.coords.longitude+"/"+e.coords.latitude;
var xhr = Ti.Network.createHTTPClient({
onload: function(e) {
// this function is called when data is returned from the server and available for use
// this.responseText holds the raw text return of the message (used for text/JSON)
// this.responseXML holds any returned XML (including SOAP)
// this.responseData holds any returned binary data
Ti.API.debug(this.responseText);
alert('success');
},
onerror: function(e) {
// this function is called when an error occurs, including a timeout
Ti.API.debug(e.error);
alert('error');
},
timeout:5000 /* in milliseconds */
});
xhr.open("GET", url);
xhr.send(); // request is actually sent with this statement
or if you plan to use more request have a look at RESTe (https://github.com/jasonkneen/RESTe) which is an awesome library that makes it easy to create API requests

Security Error when trying to load content from resource in a Firefox Addon (SDK)

I am creating a firefox addon using the SDK. My goal is simple, to intercept a specific iframe and load my own HTML page (packaged as a resource with my addon) instead of the content that was requested originally.
So far I have the following code:
var httpRequestObserver =
{
observe: function(subject, topic, data)
{
var httpChannel, requestURL;
if (topic == "http-on-modify-request") {
httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
var newRequestURL, i;
if (/someurl/.test(requestURL)) {
var ioService = Cc["#mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
httpChannel.redirectTo(ioService.newURI(self.data.url('pages/test.html'), undefined, undefined));
}
return;
}
}
};
var observerService = Cc["#mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(httpRequestObserver, "http-on-modify-request", false);
This code works in that it detects the proper iframe loading and does the redirect correctly. However, I get the following error:
Security Error: Content at http://url.com may not load or link to
jar:file:///.../pages/test.html.
How can I get around this limitation?
actually man i was really over thinking this.
its already solved when I changed to using loadContext. Now when you get loadContext you get the contentWindow of whatever browser element (tab browser, or frame or iframe) and then just abort the http request like you are doing and then loadContext.associatedWindow.document.location = self.data('pages/tests.html');
done
ill paste the code here removing all the private stuff. you might need the chrome.manifest ill test it out and paste the code back here
Cu.import('resource://gre/modules/Services.jsm');
var httpRequestObserver = {
observe: function (subject, topic, data) {
var httpChannel, requestURL;
if (topic == "http-on-modify-request") {
httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
var newRequestURL, i;
if (/someurl/.test(requestURL)) {
var goodies = loadContextGoodies(httpChannel);
if (goodies) {
httpChannel.cancel(Cr.NS_BINDING_ABORTED);
goodies.contentWindow.location = self.data.url('pages/test.html');
} else {
//dont do anything as there is no contentWindow associated with the httpChannel, liekly a google ad is loading or some ajax call or something, so this is not an error
}
}
return;
}
}
};
Services.obs.addObserver(httpRequestObserver, "http-on-modify-request", false);
//this function gets the contentWindow and other good stuff from loadContext of httpChannel
function loadContextGoodies(httpChannel) {
//httpChannel must be the subject of http-on-modify-request QI'ed to nsiHTTPChannel as is done on line 8 "httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);"
//start loadContext stuff
var loadContext;
try {
var interfaceRequestor = httpChannel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor);
//var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
try {
loadContext = interfaceRequestor.getInterface(Ci.nsILoadContext);
} catch (ex) {
try {
loadContext = subject.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
} catch (ex2) {}
}
} catch (ex0) {}
if (!loadContext) {
//no load context so dont do anything although you can run this, which is your old code
//this probably means that its loading an ajax call or like a google ad thing
return null;
} else {
var contentWindow = loadContext.associatedWindow;
if (!contentWindow) {
//this channel does not have a window, its probably loading a resource
//this probably means that its loading an ajax call or like a google ad thing
return null;
} else {
var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var gBrowser = aDOMWindow.gBrowser;
var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
var browser = aTab.linkedBrowser; //this is the browser within the tab //this is where the example in the previous section ends
return {
aDOMWindow: aDOMWindow,
gBrowser: gBrowser,
aTab: aTab,
browser: browser,
contentWindow: contentWindow
};
}
}
//end loadContext stuff
}
NOTE: Now try this first, I didn't test it yet, if you get a security error when it tries to redirect then create a chrome.manifest file and put it in the root directory. If it throws a security error than you definitely need a chrome.manifest file and that will without question fix it up. I'll test this myself later tonight when I get some time.
The chrome.manifest should look like this:
content kaboom-data ./resources/kaboom/data/ contentaccessible=yes
Then in the code way above change the redirect line from goodies.contentWindow.location = self.data.url('pages/test.html'); to goodies.contentWindow.location = 'chrome://kaboom-data/pages/test.html');.
see this addon here: https://addons.mozilla.org/en-US/firefox/addon/ghforkable/?src=search
in the chrome.manifest file we set the contentaccessible parameter to yes
you dont need sdk for this addon. its so simple, just ocpy paste that into a bootstrap skeleton as seen here:
Bootstrap With Some Features, Like chrome.manifest which you will need
Bootstrap Ultra Basic
if you want to really do a redirect of a page to your site, maybe you want to make a custom about page? if you would like ill throw togather a demo for you on making a custom about page. you can see a bit hard to understand demo here
posting my trials here so it can help all:
trail 1 failed - created chrome.manifest file with contents content kaboom-data resources/kaboom/data/ contentaccessible=yes
var myuri = Services.io.newURI('chrome://kaboom-data/content/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);
Error Thrown
Security Error: Content at http://digg.com/tools/diggthis/confirm? may
not load or link to
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/resources/kaboom/data/pages/test.html.
trial 2 failed - created resource in bootstrap.js
alias.spec =
file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi
alias updated to spec:
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/
let resource = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
let alias = Services.io.newFileURI(data.installPath);
Cu.reportError('alias.spec = ' + alias.spec);
if (!data.installPath.isDirectory()) {
alias = Services.io.newURI("jar:" + alias.spec + "!/", null, null);
Cu.reportError('alias updated to spec: ' + alias.spec);
}
resource.setSubstitution("kaboom_data", alias);
...
var myuri = Services.io.newURI('resource://kaboom_data/resources/kaboom/data/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);
Error Thrown
Security Error: Content at http://digg.com/tools/diggthis/confirm? may
not load or link to
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/resources/kaboom/data/pages/test.html.
CONCLUSION
in both trials above it was the weirdest thing, it wouldnt show the resource or chrome path in the security error thrown but it would give the full jar path. Leading me to believe that this has something to do with redirectTo function.
The solution that did work was your solution of
var gBrowser = utils.getMostRecentBrowserWindow().gBrowser;
var domWin = httpChannel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
var browser = gBrowser.getBrowserForDocument(domWin.document);
//redirect
browser.loadURI(self.data.url('pages/test.html'));
however I changed this to use loadContext instead of this method because it is the recommended way. also gBrowser to getMostRecentBrowserWindow will fail if the url load is slow and in that time the user swithces to another tab or window
I also changed to use Services.jsm as you had imported Cu anyways. Using Services.jsm is super fast not even blink fast. Its just a pointer.
Im still working on trying to the redirectTo method working its really bothering me. The changes I made are to my local copy.
Have you considered turning your local HTML file into a data URL and loading that?

Resources