Re: Android Plugin API

2014-07-11 Thread Joe Bowser
We won't be breaking plugins. I don't want to move to this for the reasons
stated before. This code also is way less maintainable, and looks like it
could break easily.  I really think that clarity should win out here over
an abuse of java reflection.

On 10 Jul,2014, at 17:15 , Anis KADRI  wrote:

> I want to say that this should be default...but we won't change the API
> again and won't break plugins again.

Both could be supported at the same time, just by using a different base
class


Re: Android Plugin API

2014-07-10 Thread Erik Jan de Wit

On 10 Jul,2014, at 17:15 , Anis KADRI  wrote:

> I want to say that this should be default...but we won't change the API
> again and won't break plugins again.

Both could be supported at the same time, just by using a different base class

Re: Android Plugin API

2014-07-10 Thread Anis KADRI
I want to say that this should be default...but we won't change the API
again and won't break plugins again.


On Thu, Jul 10, 2014 at 7:48 AM, Erik Jan de Wit  wrote:

> Hi all,
>
> Created an plugin that does this:
> https://github.com/edewit/aerogear-reflect-cordova the repository also
> includes a example plugin that uses this. Also have a blog describing this
> a bit more
> http://blog.nerdin.ch/2014/07/improved-cordova-android-plugin-api.html
>
> Cheers,
> Erik Jan
>
> On 2 Jun,2014, at 4:20 , Terence M. Bandoian  wrote:
>
> > It does get complicated in a hurry. Using the technique in the Google
> Maps plugin:
> >
> > - getDeclaredMethod is documented to NOT return inherited methods which
> limits exposure
> > - the signature passed to getDeclaredMethod also limits exposure
> > - annotations, as Andrew suggested, could further limit exposure
> >
> > - getDeclaredMethod is documented to return private methods which for me
> raises questions
> > - setAccessible(true) suppresses normal access checking which also
> raises questions
> >
> > - invoke throws InvocationTargetException so exceptions thrown by the
> invoked method could be publicized
> > - invoke applies overriding which is probably a wash
> > - invoke returns an object which would have to be handled correctly
> >
> > Quite a bit to consider.
> >
> > -Terence Bandoian
> >
> >
> > On 5/29/2014 11:44 PM, Joe Bowser wrote:
> >> On Thu, May 29, 2014 at 9:26 PM, Terence M. Bandoian 
> wrote:
> >>> Please correct me if I'm wrong but, as I understand it, the
> vulnerability
> >>> stems from injecting a Java object into the WebView which, in API
> levels 16
> >>> and below, exposed all of the public methods of the object (small 'o')
> >>> including the methods inherited from the Object class.
> >>>
> >> Yes, you are correct in this case.  You can basically use the object
> >> methods to reflect into whatever you want.  Once you have a single
> >> class exposed in this manner, you can then reflect into it, and
> >> basically you're done.  The reason we don't use reflection is that
> >> it's very easy to reflect into things you're not supposed to be in.
> >> IMO, It wouldn't be hard to do this if we exposed plugins in the same
> >> way.  Right now this is an Android Vulnerability, but if we start
> >> using reflection for plugins, we could very quickly end up making a
> >> similar Cordova exploit if we're not careful.
> >>
> >> This is also why we use the prompt bridge on API levels below 17.
> >>
> >>>
> >>>
> >>> On 5/28/2014 9:54 AM, Joe Bowser wrote:
>  In case anyone is curious, here's why we minimize reflection:
> 
> 
> 
> https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
> 
>  On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve 
>  wrote:
> > Another reasonable approach would be to use a Map,
> but
> > that can be implemented on top of what is currently exposed. I'm
> quite
> > wary
> > of Reflection as well.
> >
> >
> > On Wed, May 28, 2014 at 10:06 AM, Joe Bowser 
> wrote:
> >
> >> The execute command exists for security reasons.  We don't want any
> >> methods other than execute exposed to Javascript.  I also prefer
> this
> >> approach because it is less prone to less catastrophic bugs than
> using
> >> Java reflection.  We try and only use reflection when we have to.
> >>
> >> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit  >
> >> wrote:
> >>> Hi,
> >>>
> >>> When one is writing a plugin for android ATM the api that you have
> to
> >> implement has a execute method that has the action as a string:
> >>> @Override
> >>>  public boolean execute(String action, JSONArray args,
> >> CallbackContext callbackContext) throws JSONException {
> >>>  if ("beep".equals(action)) {
> >>>  this.beep(args.getLong(0));
> >>>  callbackContext.success();
> >>>  return true;
> >>>  }
> >>>  return false;  // Returning false results in a
> >>> "MethodNotFound"
> >> error.
> >>>  }
> >>> When you have multiple actions this method gets very long, if you
> >> compare this with iOS here you don’t need a method like this you
> could
> >> ‘just’ implement the method directly:
> >>> - (void)beep:(CDVInvokedUrlCommand*)command
> >>>  {
> >>>  CDVPluginResult* pluginResult =;
> >>>  NSString* myarg =mmand.arguments objectAtIndex:0];
> >>>
> >>>  if (myarg !=) {
> >>>  pluginResult �VPluginResult
> >> resultWithStatus:CDVCommandStatus_OK];
> >>>  } else {
> >>>  pluginResult �VPluginResult
> >> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was
> >> null"];
> >>>  }
> >>>  [self.commandDelegate sendPluginResult:pluginResult
> >> callbackId

Re: Android Plugin API

2014-07-10 Thread Erik Jan de Wit
Hi all,

Created an plugin that does this: 
https://github.com/edewit/aerogear-reflect-cordova the repository also includes 
a example plugin that uses this. Also have a blog describing this a bit more 
http://blog.nerdin.ch/2014/07/improved-cordova-android-plugin-api.html

Cheers,
Erik Jan

On 2 Jun,2014, at 4:20 , Terence M. Bandoian  wrote:

> It does get complicated in a hurry. Using the technique in the Google Maps 
> plugin:
> 
> - getDeclaredMethod is documented to NOT return inherited methods which 
> limits exposure
> - the signature passed to getDeclaredMethod also limits exposure
> - annotations, as Andrew suggested, could further limit exposure
> 
> - getDeclaredMethod is documented to return private methods which for me 
> raises questions
> - setAccessible(true) suppresses normal access checking which also raises 
> questions
> 
> - invoke throws InvocationTargetException so exceptions thrown by the invoked 
> method could be publicized
> - invoke applies overriding which is probably a wash
> - invoke returns an object which would have to be handled correctly
> 
> Quite a bit to consider.
> 
> -Terence Bandoian
> 
> 
> On 5/29/2014 11:44 PM, Joe Bowser wrote:
>> On Thu, May 29, 2014 at 9:26 PM, Terence M. Bandoian  
>> wrote:
>>> Please correct me if I'm wrong but, as I understand it, the vulnerability
>>> stems from injecting a Java object into the WebView which, in API levels 16
>>> and below, exposed all of the public methods of the object (small 'o')
>>> including the methods inherited from the Object class.
>>> 
>> Yes, you are correct in this case.  You can basically use the object
>> methods to reflect into whatever you want.  Once you have a single
>> class exposed in this manner, you can then reflect into it, and
>> basically you're done.  The reason we don't use reflection is that
>> it's very easy to reflect into things you're not supposed to be in.
>> IMO, It wouldn't be hard to do this if we exposed plugins in the same
>> way.  Right now this is an Android Vulnerability, but if we start
>> using reflection for plugins, we could very quickly end up making a
>> similar Cordova exploit if we're not careful.
>> 
>> This is also why we use the prompt bridge on API levels below 17.
>> 
>>> 
>>> 
>>> On 5/28/2014 9:54 AM, Joe Bowser wrote:
 In case anyone is curious, here's why we minimize reflection:
 
 
 https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
 
 On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve 
 wrote:
> Another reasonable approach would be to use a Map, but
> that can be implemented on top of what is currently exposed. I'm quite
> wary
> of Reflection as well.
> 
> 
> On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:
> 
>> The execute command exists for security reasons.  We don't want any
>> methods other than execute exposed to Javascript.  I also prefer this
>> approach because it is less prone to less catastrophic bugs than using
>> Java reflection.  We try and only use reflection when we have to.
>> 
>> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
>> wrote:
>>> Hi,
>>> 
>>> When one is writing a plugin for android ATM the api that you have to
>> implement has a execute method that has the action as a string:
>>> @Override
>>>  public boolean execute(String action, JSONArray args,
>> CallbackContext callbackContext) throws JSONException {
>>>  if ("beep".equals(action)) {
>>>  this.beep(args.getLong(0));
>>>  callbackContext.success();
>>>  return true;
>>>  }
>>>  return false;  // Returning false results in a
>>> "MethodNotFound"
>> error.
>>>  }
>>> When you have multiple actions this method gets very long, if you
>> compare this with iOS here you don’t need a method like this you could
>> ‘just’ implement the method directly:
>>> - (void)beep:(CDVInvokedUrlCommand*)command
>>>  {
>>>  CDVPluginResult* pluginResult =;
>>>  NSString* myarg =mmand.arguments objectAtIndex:0];
>>> 
>>>  if (myarg !=) {
>>>  pluginResult �VPluginResult
>> resultWithStatus:CDVCommandStatus_OK];
>>>  } else {
>>>  pluginResult �VPluginResult
>> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was
>> null"];
>>>  }
>>>  [self.commandDelegate sendPluginResult:pluginResult
>> callbackId:command.callbackId];
>>>  }
>>> We could do the same thing for android if we use reflection, making the
>> API more similar and removing all the string test by the user. What do
>> you
>> think?
>>> Cheers,
>>>  Erik Jan



Re: Android Plugin API

2014-06-01 Thread Terence M. Bandoian
It does get complicated in a hurry. Using the technique in the Google 
Maps plugin:


- getDeclaredMethod is documented to NOT return inherited methods which 
limits exposure

- the signature passed to getDeclaredMethod also limits exposure
- annotations, as Andrew suggested, could further limit exposure

- getDeclaredMethod is documented to return private methods which for me 
raises questions
- setAccessible(true) suppresses normal access checking which also 
raises questions


- invoke throws InvocationTargetException so exceptions thrown by the 
invoked method could be publicized

- invoke applies overriding which is probably a wash
- invoke returns an object which would have to be handled correctly

Quite a bit to consider.

-Terence Bandoian


On 5/29/2014 11:44 PM, Joe Bowser wrote:

On Thu, May 29, 2014 at 9:26 PM, Terence M. Bandoian  wrote:

Please correct me if I'm wrong but, as I understand it, the vulnerability
stems from injecting a Java object into the WebView which, in API levels 16
and below, exposed all of the public methods of the object (small 'o')
including the methods inherited from the Object class.


Yes, you are correct in this case.  You can basically use the object
methods to reflect into whatever you want.  Once you have a single
class exposed in this manner, you can then reflect into it, and
basically you're done.  The reason we don't use reflection is that
it's very easy to reflect into things you're not supposed to be in.
IMO, It wouldn't be hard to do this if we exposed plugins in the same
way.  Right now this is an Android Vulnerability, but if we start
using reflection for plugins, we could very quickly end up making a
similar Cordova exploit if we're not careful.

This is also why we use the prompt bridge on API levels below 17.




On 5/28/2014 9:54 AM, Joe Bowser wrote:

In case anyone is curious, here's why we minimize reflection:


https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/

On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve 
wrote:

Another reasonable approach would be to use a Map, but
that can be implemented on top of what is currently exposed. I'm quite
wary
of Reflection as well.


On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:


The execute command exists for security reasons.  We don't want any
methods other than execute exposed to Javascript.  I also prefer this
approach because it is less prone to less catastrophic bugs than using
Java reflection.  We try and only use reflection when we have to.

On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
wrote:

Hi,

When one is writing a plugin for android ATM the api that you have to

implement has a execute method that has the action as a string:

@Override
  public boolean execute(String action, JSONArray args,

CallbackContext callbackContext) throws JSONException {

  if ("beep".equals(action)) {
  this.beep(args.getLong(0));
  callbackContext.success();
  return true;
  }
  return false;  // Returning false results in a
"MethodNotFound"

error.

  }
When you have multiple actions this method gets very long, if you

compare this with iOS here you don’t need a method like this you could
‘just’ implement the method directly:

- (void)beep:(CDVInvokedUrlCommand*)command
  {
  CDVPluginResult* pluginResult =;
  NSString* myarg =mmand.arguments objectAtIndex:0];

  if (myarg !=) {
  pluginResult �VPluginResult

resultWithStatus:CDVCommandStatus_OK];

  } else {
  pluginResult �VPluginResult

resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was
null"];

  }
  [self.commandDelegate sendPluginResult:pluginResult

callbackId:command.callbackId];

  }
We could do the same thing for android if we use reflection, making the

API more similar and removing all the string test by the user. What do
you
think?

Cheers,
  Erik Jan






Re: Android Plugin API

2014-05-29 Thread Joe Bowser
On Thu, May 29, 2014 at 9:26 PM, Terence M. Bandoian  wrote:
> Please correct me if I'm wrong but, as I understand it, the vulnerability
> stems from injecting a Java object into the WebView which, in API levels 16
> and below, exposed all of the public methods of the object (small 'o')
> including the methods inherited from the Object class.
>

Yes, you are correct in this case.  You can basically use the object
methods to reflect into whatever you want.  Once you have a single
class exposed in this manner, you can then reflect into it, and
basically you're done.  The reason we don't use reflection is that
it's very easy to reflect into things you're not supposed to be in.
IMO, It wouldn't be hard to do this if we exposed plugins in the same
way.  Right now this is an Android Vulnerability, but if we start
using reflection for plugins, we could very quickly end up making a
similar Cordova exploit if we're not careful.

This is also why we use the prompt bridge on API levels below 17.

>
>
>
> On 5/28/2014 9:54 AM, Joe Bowser wrote:
>>
>> In case anyone is curious, here's why we minimize reflection:
>>
>>
>> https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
>>
>> On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve 
>> wrote:
>>>
>>> Another reasonable approach would be to use a Map, but
>>> that can be implemented on top of what is currently exposed. I'm quite
>>> wary
>>> of Reflection as well.
>>>
>>>
>>> On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:
>>>
 The execute command exists for security reasons.  We don't want any
 methods other than execute exposed to Javascript.  I also prefer this
 approach because it is less prone to less catastrophic bugs than using
 Java reflection.  We try and only use reflection when we have to.

 On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
 wrote:
>
> Hi,
>
> When one is writing a plugin for android ATM the api that you have to

 implement has a execute method that has the action as a string:
>
> @Override
>  public boolean execute(String action, JSONArray args,

 CallbackContext callbackContext) throws JSONException {
>
>  if ("beep".equals(action)) {
>  this.beep(args.getLong(0));
>  callbackContext.success();
>  return true;
>  }
>  return false;  // Returning false results in a
> "MethodNotFound"

 error.
>
>  }
> When you have multiple actions this method gets very long, if you

 compare this with iOS here you don’t need a method like this you could
 ‘just’ implement the method directly:
>
> - (void)beep:(CDVInvokedUrlCommand*)command
>  {
>  CDVPluginResult* pluginResult =il;
>  NSString* myarg =command.arguments objectAtIndex:0];
>
>  if (myarg !=il) {
>  pluginResult =CDVPluginResult

 resultWithStatus:CDVCommandStatus_OK];
>
>  } else {
>  pluginResult =CDVPluginResult

 resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was
 null"];
>
>  }
>  [self.commandDelegate sendPluginResult:pluginResult

 callbackId:command.callbackId];
>
>  }
> We could do the same thing for android if we use reflection, making the

 API more similar and removing all the string test by the user. What do
 you
 think?
>
> Cheers,
>  Erik Jan
>
>


Re: Android Plugin API

2014-05-29 Thread Terence M. Bandoian
Please correct me if I'm wrong but, as I understand it, the 
vulnerability stems from injecting a Java object into the WebView which, 
in API levels 16 and below, exposed all of the public methods of the 
object (small 'o') including the methods inherited from the Object class.


-Terence Bandoian


On 5/28/2014 9:54 AM, Joe Bowser wrote:

In case anyone is curious, here's why we minimize reflection:

https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/

On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve  wrote:

Another reasonable approach would be to use a Map, but
that can be implemented on top of what is currently exposed. I'm quite wary
of Reflection as well.


On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:


The execute command exists for security reasons.  We don't want any
methods other than execute exposed to Javascript.  I also prefer this
approach because it is less prone to less catastrophic bugs than using
Java reflection.  We try and only use reflection when we have to.

On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
wrote:

Hi,

When one is writing a plugin for android ATM the api that you have to

implement has a execute method that has the action as a string:

@Override
 public boolean execute(String action, JSONArray args,

CallbackContext callbackContext) throws JSONException {

 if ("beep".equals(action)) {
 this.beep(args.getLong(0));
 callbackContext.success();
 return true;
 }
 return false;  // Returning false results in a "MethodNotFound"

error.

 }
When you have multiple actions this method gets very long, if you

compare this with iOS here you don’t need a method like this you could
‘just’ implement the method directly:

- (void)beep:(CDVInvokedUrlCommand*)command
 {
 CDVPluginResult* pluginResult =il;
 NSString* myarg =command.arguments objectAtIndex:0];

 if (myarg !=il) {
 pluginResult =CDVPluginResult

resultWithStatus:CDVCommandStatus_OK];

 } else {
 pluginResult =CDVPluginResult

resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];

 }
 [self.commandDelegate sendPluginResult:pluginResult

callbackId:command.callbackId];

 }
We could do the same thing for android if we use reflection, making the

API more similar and removing all the string test by the user. What do you
think?

Cheers,
 Erik Jan




Re: Android Plugin API

2014-05-29 Thread Andrew Grieve
Even even nicer might be to use annotations:

@ExecCall
private void someCall(JSONArray args, CallbackContext callbackContext)


On Thu, May 29, 2014 at 4:01 PM, Joe Bowser  wrote:

> This plugin illustrates why applying this to the general case is a
> terrible idea.  Here it's catching every type of exception, which is
> correct since we don't know whether we're running on a device that
> passes CTS.  However, for example, if there's a permissions problem,
> or a problem with the GPS being busted, we have to rely on a stack
> trace in logcat and it won't crash.  I personally prefer crashing over
> silent failing, since one will get caught in my debugger, and one will
> have me sifting through logcat and will go undetected for months.  If
> you don't know what I'm talking about, go look at Camera or File!!!
>
> I'm not sure what exceptions Google Maps throws, but debugging a
> Google Maps problem would be a nightmare since this will catch all the
> exceptions.  You can do this at your own peril.
>
> On Thu, May 29, 2014 at 12:29 PM, Michal Mocny 
> wrote:
> > Erik,
> >
> > I think it should be possible leave the platform plugin interface as-is,
> > and publish a plugin that does nothing but implement
> > reflection-based-execute.  Then, plugin authors can opt to use that as a
> > base class for plugin development.
> >
> > I hesitate to give opinions on this topic, except to say that its also
> > something I've thought would be useful, but not enough of a big deal to
> > make a stink over it.
> >
> > Andrew also points out that there are plugins that have been published
> that
> > use this approach, i.e.:
> >
> https://github.com/wf9a5m75/phonegap-googlemaps-plugin/blob/master/src/android/plugin/google/maps/MyPlugin.java#L45-L57
> >
> >
> > On Thu, May 29, 2014 at 3:01 PM, Joe Bowser  wrote:
> >
> >> On Thu, May 29, 2014 at 11:46 AM, Erik Jan de Wit 
> >> wrote:
> >> >
> >> >> What is the benefit of using this logic?  I personally don't see any
> >> >> benefit, since this makes our code more complex.
> >> >
> >> > It would benefit the users as they don’t have to implement this
> >> boilerplate code of dispatching based on the string. And this logic
> will be
> >> then on the android side where it’s implemented once instead of each
> time
> >> one is building a plugin.
> >>
> >> Except that now every method exposed has to have a particular
> >> signature.  I personally would rather see us use a Map as what Andrew
> >> suggested, and I really don't want this to happen.  This is going to
> >> cause a lot more problems than it's going to solve since plugins that
> >> already throw exceptions may end up having it caught by the try/catch
> >> which will surround this whole thing.  This is a BIG change in the
> >> API, and I don't think your reason justifies breaking every plugin
> >> that currently exists.
> >>
>


Re: Android Plugin API

2014-05-29 Thread Joe Bowser
This plugin illustrates why applying this to the general case is a
terrible idea.  Here it's catching every type of exception, which is
correct since we don't know whether we're running on a device that
passes CTS.  However, for example, if there's a permissions problem,
or a problem with the GPS being busted, we have to rely on a stack
trace in logcat and it won't crash.  I personally prefer crashing over
silent failing, since one will get caught in my debugger, and one will
have me sifting through logcat and will go undetected for months.  If
you don't know what I'm talking about, go look at Camera or File!!!

I'm not sure what exceptions Google Maps throws, but debugging a
Google Maps problem would be a nightmare since this will catch all the
exceptions.  You can do this at your own peril.

On Thu, May 29, 2014 at 12:29 PM, Michal Mocny  wrote:
> Erik,
>
> I think it should be possible leave the platform plugin interface as-is,
> and publish a plugin that does nothing but implement
> reflection-based-execute.  Then, plugin authors can opt to use that as a
> base class for plugin development.
>
> I hesitate to give opinions on this topic, except to say that its also
> something I've thought would be useful, but not enough of a big deal to
> make a stink over it.
>
> Andrew also points out that there are plugins that have been published that
> use this approach, i.e.:
> https://github.com/wf9a5m75/phonegap-googlemaps-plugin/blob/master/src/android/plugin/google/maps/MyPlugin.java#L45-L57
>
>
> On Thu, May 29, 2014 at 3:01 PM, Joe Bowser  wrote:
>
>> On Thu, May 29, 2014 at 11:46 AM, Erik Jan de Wit 
>> wrote:
>> >
>> >> What is the benefit of using this logic?  I personally don't see any
>> >> benefit, since this makes our code more complex.
>> >
>> > It would benefit the users as they don’t have to implement this
>> boilerplate code of dispatching based on the string. And this logic will be
>> then on the android side where it’s implemented once instead of each time
>> one is building a plugin.
>>
>> Except that now every method exposed has to have a particular
>> signature.  I personally would rather see us use a Map as what Andrew
>> suggested, and I really don't want this to happen.  This is going to
>> cause a lot more problems than it's going to solve since plugins that
>> already throw exceptions may end up having it caught by the try/catch
>> which will surround this whole thing.  This is a BIG change in the
>> API, and I don't think your reason justifies breaking every plugin
>> that currently exists.
>>


Re: Android Plugin API

2014-05-29 Thread Jesse
I am with Joe, this is too big and breaking of a change for a small
semantic win.

Another approach might be to define an execute method in a plugin ( pick
one ) and have it self reflect, and call it's own exposed methods.

@Override
public boolean execute(String action, JSONArray args, CallbackContext
callbackContext) throws JSONException {

// pseudocode ...
if(this[action]) {
   return this[action](args, callbackContext);
}

return false;  // Returning false results in a "MethodNotFound"
error.
}

Then every callable method would be :
boolean methodName(JSONArray args, CallbackContext callbackContext) throws
JSONException

Potentially this could become the base class implementation of 'execute'
and presumably nothing would break ...




@purplecabbage
risingj.com


On Thu, May 29, 2014 at 12:01 PM, Joe Bowser  wrote:

> On Thu, May 29, 2014 at 11:46 AM, Erik Jan de Wit 
> wrote:
> >
> >> What is the benefit of using this logic?  I personally don't see any
> >> benefit, since this makes our code more complex.
> >
> > It would benefit the users as they don’t have to implement this
> boilerplate code of dispatching based on the string. And this logic will be
> then on the android side where it’s implemented once instead of each time
> one is building a plugin.
>
> Except that now every method exposed has to have a particular
> signature.  I personally would rather see us use a Map as what Andrew
> suggested, and I really don't want this to happen.  This is going to
> cause a lot more problems than it's going to solve since plugins that
> already throw exceptions may end up having it caught by the try/catch
> which will surround this whole thing.  This is a BIG change in the
> API, and I don't think your reason justifies breaking every plugin
> that currently exists.
>


Re: Android Plugin API

2014-05-29 Thread Michal Mocny
Erik,

I think it should be possible leave the platform plugin interface as-is,
and publish a plugin that does nothing but implement
reflection-based-execute.  Then, plugin authors can opt to use that as a
base class for plugin development.

I hesitate to give opinions on this topic, except to say that its also
something I've thought would be useful, but not enough of a big deal to
make a stink over it.

Andrew also points out that there are plugins that have been published that
use this approach, i.e.:
https://github.com/wf9a5m75/phonegap-googlemaps-plugin/blob/master/src/android/plugin/google/maps/MyPlugin.java#L45-L57


On Thu, May 29, 2014 at 3:01 PM, Joe Bowser  wrote:

> On Thu, May 29, 2014 at 11:46 AM, Erik Jan de Wit 
> wrote:
> >
> >> What is the benefit of using this logic?  I personally don't see any
> >> benefit, since this makes our code more complex.
> >
> > It would benefit the users as they don’t have to implement this
> boilerplate code of dispatching based on the string. And this logic will be
> then on the android side where it’s implemented once instead of each time
> one is building a plugin.
>
> Except that now every method exposed has to have a particular
> signature.  I personally would rather see us use a Map as what Andrew
> suggested, and I really don't want this to happen.  This is going to
> cause a lot more problems than it's going to solve since plugins that
> already throw exceptions may end up having it caught by the try/catch
> which will surround this whole thing.  This is a BIG change in the
> API, and I don't think your reason justifies breaking every plugin
> that currently exists.
>


Re: Android Plugin API

2014-05-29 Thread Joe Bowser
On Thu, May 29, 2014 at 11:46 AM, Erik Jan de Wit  wrote:
>
>> What is the benefit of using this logic?  I personally don't see any
>> benefit, since this makes our code more complex.
>
> It would benefit the users as they don’t have to implement this boilerplate 
> code of dispatching based on the string. And this logic will be then on the 
> android side where it’s implemented once instead of each time one is building 
> a plugin.

Except that now every method exposed has to have a particular
signature.  I personally would rather see us use a Map as what Andrew
suggested, and I really don't want this to happen.  This is going to
cause a lot more problems than it's going to solve since plugins that
already throw exceptions may end up having it caught by the try/catch
which will surround this whole thing.  This is a BIG change in the
API, and I don't think your reason justifies breaking every plugin
that currently exists.


Re: Android Plugin API

2014-05-29 Thread Erik Jan de Wit

> What is the benefit of using this logic?  I personally don't see any
> benefit, since this makes our code more complex.

It would benefit the users as they don’t have to implement this boilerplate 
code of dispatching based on the string. And this logic will be then on the 
android side where it’s implemented once instead of each time one is building a 
plugin. 

Re: Android Plugin API

2014-05-29 Thread Erik Jan de Wit
I could build a little prototype that shows what I’m talking about, how does 
that sound?

Re: Android Plugin API

2014-05-29 Thread Joe Bowser
On Thu, May 29, 2014 at 1:25 AM, Erik Jan de Wit  wrote:
>
> On 28 May,2014, at 22:07 , Shazron  wrote:
>
>> https://github.com/apache/cordova-ios/blob/50ca482c8e861c1aa480dadba726b1abbacbc0e1/CordovaLib/Classes/CDVCommandQueue.m#L193-L198
>
> Right thanks, that is how I expected it to work, so why not use the same 
> logic in Android as on iOS? In Java one can also find a method based on the 
> action name and invoke it. I would say it’s less error prone then doing 
> string comparison yourself.
>

What is the benefit of using this logic?  I personally don't see any
benefit, since this makes our code more complex.

>>
>>
>> On Wed, May 28, 2014 at 12:05 PM, Erik Jan de Wit  wrote:
>>
>>>

 I don't know, it very much could be.  It could be that this makes sense
>>> in
 Obj-C but not in Java based on how they handle NoSuchMethod.  I'd prefer
>>> to
 not have to rely on an exception being caught, especially since it could
 suppress other exceptions being thrown that I want to know about.
>>>
>>> Sending a message (calling a method) in object-c for a method that doesn’t
>>> exist will also throw an exception, I haven’t looked at the implementation
>>> but I would suspect that there is a test to see if the method (selector) is
>>> there.
>>>

 Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
 assumption given that each device has their own quirks and this isn't
 guaranteed.
>>>
>>> One could just lookup if the method exist and not just try to invoke it
>>> and wait for the NoSuchMethod. That way one could make the error handling
>>> nicer, for example:
>>>
>>> You have a method called ‘myAction’ but it does not have the proper method
>>> signature! Found public void myAction() but should be pubic PluginResult
>>> myAction(JSONArray, CallbackContext)
>>>
>>>
>


Re: Android Plugin API

2014-05-29 Thread Erik Jan de Wit

On 28 May,2014, at 22:07 , Shazron  wrote:

> https://github.com/apache/cordova-ios/blob/50ca482c8e861c1aa480dadba726b1abbacbc0e1/CordovaLib/Classes/CDVCommandQueue.m#L193-L198

Right thanks, that is how I expected it to work, so why not use the same logic 
in Android as on iOS? In Java one can also find a method based on the action 
name and invoke it. I would say it’s less error prone then doing string 
comparison yourself. 

> 
> 
> On Wed, May 28, 2014 at 12:05 PM, Erik Jan de Wit  wrote:
> 
>> 
>>> 
>>> I don't know, it very much could be.  It could be that this makes sense
>> in
>>> Obj-C but not in Java based on how they handle NoSuchMethod.  I'd prefer
>> to
>>> not have to rely on an exception being caught, especially since it could
>>> suppress other exceptions being thrown that I want to know about.
>> 
>> Sending a message (calling a method) in object-c for a method that doesn’t
>> exist will also throw an exception, I haven’t looked at the implementation
>> but I would suspect that there is a test to see if the method (selector) is
>> there.
>> 
>>> 
>>> Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
>>> assumption given that each device has their own quirks and this isn't
>>> guaranteed.
>> 
>> One could just lookup if the method exist and not just try to invoke it
>> and wait for the NoSuchMethod. That way one could make the error handling
>> nicer, for example:
>> 
>> You have a method called ‘myAction’ but it does not have the proper method
>> signature! Found public void myAction() but should be pubic PluginResult
>> myAction(JSONArray, CallbackContext)
>> 
>> 



Re: Android Plugin API

2014-05-28 Thread Shazron
https://github.com/apache/cordova-ios/blob/50ca482c8e861c1aa480dadba726b1abbacbc0e1/CordovaLib/Classes/CDVCommandQueue.m#L193-L198


On Wed, May 28, 2014 at 12:05 PM, Erik Jan de Wit  wrote:

>
> >
> > I don't know, it very much could be.  It could be that this makes sense
> in
> > Obj-C but not in Java based on how they handle NoSuchMethod.  I'd prefer
> to
> > not have to rely on an exception being caught, especially since it could
> > suppress other exceptions being thrown that I want to know about.
>
> Sending a message (calling a method) in object-c for a method that doesn’t
> exist will also throw an exception, I haven’t looked at the implementation
> but I would suspect that there is a test to see if the method (selector) is
> there.
>
> >
> > Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
> > assumption given that each device has their own quirks and this isn't
> > guaranteed.
>
> One could just lookup if the method exist and not just try to invoke it
> and wait for the NoSuchMethod. That way one could make the error handling
> nicer, for example:
>
> You have a method called ‘myAction’ but it does not have the proper method
> signature! Found public void myAction() but should be pubic PluginResult
> myAction(JSONArray, CallbackContext)
>
>


Re: Android Plugin API

2014-05-28 Thread Naik, Archana
iOS has [object respondsToSelector:@selector(selector)] to check if
selector exists or not.


On 5/28/14 12:05 PM, "Erik Jan de Wit"  wrote:

>
>> 
>> I don't know, it very much could be.  It could be that this makes sense
>>in
>> Obj-C but not in Java based on how they handle NoSuchMethod.  I'd
>>prefer to
>> not have to rely on an exception being caught, especially since it could
>> suppress other exceptions being thrown that I want to know about.
>
>Sending a message (calling a method) in object-c for a method that
>doesn¹t exist will also throw an exception, I haven¹t looked at the
>implementation but I would suspect that there is a test to see if the
>method (selector) is there.
>
>> 
>> Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
>> assumption given that each device has their own quirks and this isn't
>> guaranteed.
>
>One could just lookup if the method exist and not just try to invoke it
>and wait for the NoSuchMethod. That way one could make the error handling
>nicer, for example:
>
>You have a method called ŒmyAction¹ but it does not have the proper
>method signature! Found public void myAction() but should be pubic
>PluginResult myAction(JSONArray, CallbackContext)
>



Re: Android Plugin API

2014-05-28 Thread Erik Jan de Wit

> 
> I don't know, it very much could be.  It could be that this makes sense in
> Obj-C but not in Java based on how they handle NoSuchMethod.  I'd prefer to
> not have to rely on an exception being caught, especially since it could
> suppress other exceptions being thrown that I want to know about.

Sending a message (calling a method) in object-c for a method that doesn’t 
exist will also throw an exception, I haven’t looked at the implementation but 
I would suspect that there is a test to see if the method (selector) is there.

> 
> Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
> assumption given that each device has their own quirks and this isn't
> guaranteed.

One could just lookup if the method exist and not just try to invoke it and 
wait for the NoSuchMethod. That way one could make the error handling nicer, 
for example: 

You have a method called ‘myAction’ but it does not have the proper method 
signature! Found public void myAction() but should be pubic PluginResult 
myAction(JSONArray, CallbackContext)



Re: Android Plugin API

2014-05-28 Thread Joe Bowser
On May 28, 2014 11:21 AM, "Erik Jan de Wit"  wrote:
>
>
> On 28 May,2014, at 19:06 , Joe Bowser  wrote:
>
> > We don't want this pattern for Android because it is also more bug
prone.
>
> Doesn’t the same hold true for iOS?
>

I don't know, it very much could be.  It could be that this makes sense in
Obj-C but not in Java based on how they handle NoSuchMethod.  I'd prefer to
not have to rely on an exception being caught, especially since it could
suppress other exceptions being thrown that I want to know about.

Also, I'm assuming the exception is NoSuchMethod, which isn't a safe
assumption given that each device has their own quirks and this isn't
guaranteed.

> >
> > On May 28, 2014 8:28 AM, "Erik Jan de Wit"  wrote:
> >>
> >> So this security issue is only a problem if you are able to inject some
> > arbitrary js code. If your app ships with it’s own html and js this is
very
> > hard to do.
> >
> > No, it's not. Any trusted input could have the potential to inject JS.
> > We're not even touching on the third-party ad networks code, frameworks
or
> > other code that developers add on a regular basis.
>
> Still in the example android permits any method to be executed (getClass)
there could be checks. For instance only public methods that have a
JSONArray and a CallbackContext as parameters and have the name of the
action. That way you can’t inject any arbitrary code. If a user implements
the wrong method the error logging can be in a way that one can easily
correct the issue, because of these checks.
>


Re: Android Plugin API

2014-05-28 Thread Erik Jan de Wit

On 28 May,2014, at 19:06 , Joe Bowser  wrote:

> We don't want this pattern for Android because it is also more bug prone.

Doesn’t the same hold true for iOS?

> 
> On May 28, 2014 8:28 AM, "Erik Jan de Wit"  wrote:
>> 
>> So this security issue is only a problem if you are able to inject some
> arbitrary js code. If your app ships with it’s own html and js this is very
> hard to do.
> 
> No, it's not. Any trusted input could have the potential to inject JS.
> We're not even touching on the third-party ad networks code, frameworks or
> other code that developers add on a regular basis.

Still in the example android permits any method to be executed (getClass) there 
could be checks. For instance only public methods that have a JSONArray and a 
CallbackContext as parameters and have the name of the action. That way you 
can’t inject any arbitrary code. If a user implements the wrong method the 
error logging can be in a way that one can easily correct the issue, because of 
these checks.



Re: Android Plugin API

2014-05-28 Thread Joe Bowser
We don't want this pattern for Android because it is also more bug prone.

On May 28, 2014 8:28 AM, "Erik Jan de Wit"  wrote:
>
> So this security issue is only a problem if you are able to inject some
arbitrary js code. If your app ships with it’s own html and js this is very
hard to do.

No, it's not. Any trusted input could have the potential to inject JS.
We're not even touching on the third-party ad networks code, frameworks or
other code that developers add on a regular basis.


Re: Android Plugin API

2014-05-28 Thread Erik Jan de Wit
So this security issue is only a problem if you are able to inject some 
arbitrary js code. If your app ships with it’s own html and js this is very 
hard to do. If the only reason for this is security then why not have the same 
approach on iOS here methods are invoked dynamicly.

On 28 May,2014, at 16:54 , Joe Bowser  wrote:

> In case anyone is curious, here's why we minimize reflection:
> 
> https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/
> 
> On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve  wrote:
>> Another reasonable approach would be to use a Map, but
>> that can be implemented on top of what is currently exposed. I'm quite wary
>> of Reflection as well.
>> 
>> 
>> On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:
>> 
>>> The execute command exists for security reasons.  We don't want any
>>> methods other than execute exposed to Javascript.  I also prefer this
>>> approach because it is less prone to less catastrophic bugs than using
>>> Java reflection.  We try and only use reflection when we have to.
>>> 
>>> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
>>> wrote:
 Hi,
 
 When one is writing a plugin for android ATM the api that you have to
>>> implement has a execute method that has the action as a string:
 @Override
public boolean execute(String action, JSONArray args,
>>> CallbackContext callbackContext) throws JSONException {
if ("beep".equals(action)) {
this.beep(args.getLong(0));
callbackContext.success();
return true;
}
return false;  // Returning false results in a "MethodNotFound"
>>> error.
}
 When you have multiple actions this method gets very long, if you
>>> compare this with iOS here you don’t need a method like this you could
>>> ‘just’ implement the method directly:
 - (void)beep:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* myarg = [command.arguments objectAtIndex:0];
 
if (myarg != nil) {
pluginResult = [CDVPluginResult
>>> resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult
>>> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
}
[self.commandDelegate sendPluginResult:pluginResult
>>> callbackId:command.callbackId];
}
 We could do the same thing for android if we use reflection, making the
>>> API more similar and removing all the string test by the user. What do you
>>> think?
 
 Cheers,
Erik Jan
>>> 



Re: Android Plugin API

2014-05-28 Thread Joe Bowser
In case anyone is curious, here's why we minimize reflection:

https://labs.mwrinfosecurity.com/blog/2013/09/24/webview-addjavascriptinterface-remote-code-execution/

On Wed, May 28, 2014 at 7:33 AM, Andrew Grieve  wrote:
> Another reasonable approach would be to use a Map, but
> that can be implemented on top of what is currently exposed. I'm quite wary
> of Reflection as well.
>
>
> On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:
>
>> The execute command exists for security reasons.  We don't want any
>> methods other than execute exposed to Javascript.  I also prefer this
>> approach because it is less prone to less catastrophic bugs than using
>> Java reflection.  We try and only use reflection when we have to.
>>
>> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
>> wrote:
>> > Hi,
>> >
>> > When one is writing a plugin for android ATM the api that you have to
>> implement has a execute method that has the action as a string:
>> > @Override
>> > public boolean execute(String action, JSONArray args,
>> CallbackContext callbackContext) throws JSONException {
>> > if ("beep".equals(action)) {
>> > this.beep(args.getLong(0));
>> > callbackContext.success();
>> > return true;
>> > }
>> > return false;  // Returning false results in a "MethodNotFound"
>> error.
>> > }
>> > When you have multiple actions this method gets very long, if you
>> compare this with iOS here you don’t need a method like this you could
>> ‘just’ implement the method directly:
>> > - (void)beep:(CDVInvokedUrlCommand*)command
>> > {
>> > CDVPluginResult* pluginResult = nil;
>> > NSString* myarg = [command.arguments objectAtIndex:0];
>> >
>> > if (myarg != nil) {
>> > pluginResult = [CDVPluginResult
>> resultWithStatus:CDVCommandStatus_OK];
>> > } else {
>> > pluginResult = [CDVPluginResult
>> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
>> > }
>> > [self.commandDelegate sendPluginResult:pluginResult
>> callbackId:command.callbackId];
>> > }
>> > We could do the same thing for android if we use reflection, making the
>> API more similar and removing all the string test by the user. What do you
>> think?
>> >
>> > Cheers,
>> > Erik Jan
>>


Re: Android Plugin API

2014-05-28 Thread Andrew Grieve
Another reasonable approach would be to use a Map, but
that can be implemented on top of what is currently exposed. I'm quite wary
of Reflection as well.


On Wed, May 28, 2014 at 10:06 AM, Joe Bowser  wrote:

> The execute command exists for security reasons.  We don't want any
> methods other than execute exposed to Javascript.  I also prefer this
> approach because it is less prone to less catastrophic bugs than using
> Java reflection.  We try and only use reflection when we have to.
>
> On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit 
> wrote:
> > Hi,
> >
> > When one is writing a plugin for android ATM the api that you have to
> implement has a execute method that has the action as a string:
> > @Override
> > public boolean execute(String action, JSONArray args,
> CallbackContext callbackContext) throws JSONException {
> > if ("beep".equals(action)) {
> > this.beep(args.getLong(0));
> > callbackContext.success();
> > return true;
> > }
> > return false;  // Returning false results in a "MethodNotFound"
> error.
> > }
> > When you have multiple actions this method gets very long, if you
> compare this with iOS here you don’t need a method like this you could
> ‘just’ implement the method directly:
> > - (void)beep:(CDVInvokedUrlCommand*)command
> > {
> > CDVPluginResult* pluginResult = nil;
> > NSString* myarg = [command.arguments objectAtIndex:0];
> >
> > if (myarg != nil) {
> > pluginResult = [CDVPluginResult
> resultWithStatus:CDVCommandStatus_OK];
> > } else {
> > pluginResult = [CDVPluginResult
> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
> > }
> > [self.commandDelegate sendPluginResult:pluginResult
> callbackId:command.callbackId];
> > }
> > We could do the same thing for android if we use reflection, making the
> API more similar and removing all the string test by the user. What do you
> think?
> >
> > Cheers,
> > Erik Jan
>


Re: Android Plugin API

2014-05-28 Thread Joe Bowser
The execute command exists for security reasons.  We don't want any
methods other than execute exposed to Javascript.  I also prefer this
approach because it is less prone to less catastrophic bugs than using
Java reflection.  We try and only use reflection when we have to.

On Wed, May 28, 2014 at 5:50 AM, Erik Jan de Wit  wrote:
> Hi,
>
> When one is writing a plugin for android ATM the api that you have to 
> implement has a execute method that has the action as a string:
> @Override
> public boolean execute(String action, JSONArray args, CallbackContext 
> callbackContext) throws JSONException {
> if ("beep".equals(action)) {
> this.beep(args.getLong(0));
> callbackContext.success();
> return true;
> }
> return false;  // Returning false results in a "MethodNotFound" error.
> }
> When you have multiple actions this method gets very long, if you compare 
> this with iOS here you don’t need a method like this you could ‘just’ 
> implement the method directly:
> - (void)beep:(CDVInvokedUrlCommand*)command
> {
> CDVPluginResult* pluginResult = nil;
> NSString* myarg = [command.arguments objectAtIndex:0];
>
> if (myarg != nil) {
> pluginResult = [CDVPluginResult 
> resultWithStatus:CDVCommandStatus_OK];
> } else {
> pluginResult = [CDVPluginResult 
> resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
> }
> [self.commandDelegate sendPluginResult:pluginResult 
> callbackId:command.callbackId];
> }
> We could do the same thing for android if we use reflection, making the API 
> more similar and removing all the string test by the user. What do you think?
>
> Cheers,
> Erik Jan


Android Plugin API

2014-05-28 Thread Erik Jan de Wit
Hi,

When one is writing a plugin for android ATM the api that you have to implement 
has a execute method that has the action as a string:
@Override
public boolean execute(String action, JSONArray args, CallbackContext 
callbackContext) throws JSONException {
if ("beep".equals(action)) {
this.beep(args.getLong(0));
callbackContext.success();
return true;
}
return false;  // Returning false results in a "MethodNotFound" error.
}
When you have multiple actions this method gets very long, if you compare this 
with iOS here you don’t need a method like this you could ‘just’ implement the 
method directly:
- (void)beep:(CDVInvokedUrlCommand*)command
{
CDVPluginResult* pluginResult = nil;
NSString* myarg = [command.arguments objectAtIndex:0];

if (myarg != nil) {
pluginResult = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_OK];
} else {
pluginResult = [CDVPluginResult 
resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
}
[self.commandDelegate sendPluginResult:pluginResult 
callbackId:command.callbackId];
}
We could do the same thing for android if we use reflection, making the API 
more similar and removing all the string test by the user. What do you think?

Cheers,
Erik Jan