15 Replies Latest reply: Nov 25, 2016 10:00 AM by Mark Sohm RSS

Using 10.3.2 API's?

tjmavrakis Novice

The latest available API levels for Momentics IDE is 10.3.1. They said there were NO changes to the API in 10.3.2 or in 10.3.3. 

 

In the documentation for WebSettings, it shows some methods that are available "Since 10.3.2." For instance the methods for the property "certificatePath"

 

https://developer.blackberry.com/native/reference/cascades/bb__cascades__websettings.html#property-certificatepath

 

I have 10.3.2 installed on my device. But when I try to use the method setCertificatePath() in C++ it gives me a compile error, since that method is not available in the 10.3.1 API level i have installed in Momentics. 

 

I am very suprised that there is no other mention of this discrepancy on this forum, or anywhere on the web at all. 

 

If those methods are available in 10.3.2, how can I use them?

 

Thank you,
Theo

  • Re: Using 10.3.2 API's?
    roger04 Expert
    10.3.2 is available, here's how to update :

    On the Help menu, click Update API Levels.
    In the API Levels dialog box, select the tab for the type of API level that you want to install (Gold or Beta).
    Click Install for the API level that you want to install.
    When the API level finishes installing, click OK.

    https://developer.blackberry.com/native/documentation/dev/tools/api_levels.html

    Don't forget to set the API level for your project after downloading the new API and rebuild. If your app is an headless app, you'll have to do it with both UI and headless.
    • Re: Using 10.3.2 API's?
      tjmavrakis Novice

      Are you seeing something I am not? There are no API levels in the "Beta" tab. In the "Gold" there is only 10.3.1, 10.3, 10.2, 10.1 and 10.0.

      Where exactly do you see 10.3.2 available as an API level to download?

       

      Edit: I forgot to mention I am on version 2.1.2 of Momentics and clicked "Help->Check for Updates" which didn't do anything.

  • Re: Using 10.3.2 API's?
    roger04 Expert
    I'm not home, will check when I get home later today.
  • Re: Using 10.3.2 API's?
    roger04 Expert
    Hummmm... You're right, it's probably only available in QML through
    import bb.cascades 1.4
    • Re: Using 10.3.2 API's?
      Mark Sohm BlackBerry Employee

      There is no BlackBerry 10.3.2 SDK, beta or otherwise.  The last version of SDK released is 10.3.1.  There were a couple minor certificate handling methods added in 10.3.2 at the request of some government agencies, including the one you mention above.  These were not released publicly.  

  • Re: Using 10.3.2 API's?
    roger04 Expert

    @MSohm is right, it's not available in QML either.

     

    Following this awesome blog post from @dkonigs, I've created a sample code for you to dynamically link to the function included in the OS, I've tested this code on my Passport running 10.3.2 and it seems to work, though I didn't provided a real certificate.

     

    #include "applicationui.hpp"
    
    #include <bb/cascades/Application>
    #include <bb/cascades/QmlDocument>
    #include <bb/cascades/AbstractPane>
    
    #include <dlfcn.h>
    #include <bbndk.h>
    
    using namespace bb::cascades;
    
    ApplicationUI::ApplicationUI() :
            QObject()
    {
        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
        AbstractPane *root = qml->createRootObject<AbstractPane>();
        Application::instance()->setScene(root);
    
        WebView* webView = new WebView();
        WebSettings* webSettings = webView->settings();
    //    webSettings->setCertificatePath("file:///dumb.path"); <- Won't work
        this->setCertificatePath(webSettings, "file:///myCert.path");
    }
    
    void ApplicationUI::setCertificatePath(WebSettings *webSettings, const QString &path)
    {
    #if BBNDK_VERSION_AT_LEAST(10,3,2)
        // Bind to setCertificatePath() function
        void (*webSettings_setCertificatePath)(WebSettings *, QString) = (void (*)(WebSettings *, QString))dlsym(RTLD_DEFAULT, "_ZN2bb8cascades11WebSettings18setCertificatePathERK7QString");
        if(!webSettings_setCertificatePath) {
            qDebug() << "dlsym failed (webSettings_setCertificatePath):" << dlerror();
            return;
        }
    
        // Bind to certificatePath() function
        QString (*webSettings_certificatePath)(WebSettings *) = (QString (*)(WebSettings *))dlsym(RTLD_DEFAULT, "_ZNK2bb8cascades11WebSettings15certificatePathEv");
        if(!webSettings_certificatePath) {
            qDebug() << "dlsym failed (webSettings_certificatePath):" << dlerror();
            return;
        }
    
        webSettings_setCertificatePath(webSettings, path);
        qDebug() << webSettings_certificatePath(webSettings);
    #else
        qDebug() << "setCertificatePath() was introduced in 10.3.2, please update your OS to use this feature";
    #endif
    }
    • Re: Using 10.3.2 API's?
      tjmavrakis Novice
      Ok I tested your code. Unfortunately when it gets to the setCertificatePath() function, it jumps straight past the #if statement and console shows "setCertificatePath() was introduced in 10.3.2, please update your OS to use this feature"; But of course the device I am testing on is running 10.3.2...

      You mentioned getting the libbbcascades.so file from your Passport. Do i need to replace some local file on my machine with that .so file?
      • Re: Using 10.3.2 API's?
        tjmavrakis Novice

        This is what my log is looking like. Not sure what those last two mean....

         

         

        Nov 25 05:58:28.865 redditinmotion.testDev_ditinmotion50ed1579.445993225 default 9000 INFO "setCertificatePath() - path: /app/native/assets/certs/"

        Nov 25 05:58:28.866 redditinmotion.testDev_ditinmotion50ed1579.445993225 default 9000 INFO "/app/native/assets/certs/"

        Nov 25 05:58:28.975 redditinmotion.testDev_ditinmotion50ed1579.445993225 default 0 INFO Disabling certmgr for verification due to custom cert path /app/native/assets/certs/

        Nov 25 05:59:41.764 redditinmotion.testDev_ditinmotion50ed1579.446632201 default 0 CRITICAL CertMgrWrapper: certmgr_Init(): error 13

        Nov 25 05:59:41.764 redditinmotion.testDev_ditinmotion50ed1579.446632201 default 0 CRITICAL CertMgrWrapper: unable to access new certmgr.

         

        EDIT: Ok those last two errors show up in the logs anytime I try to open gfycat in WebView, even without trying to add the custom certs.

        • Re: Using 10.3.2 API's?
          tjmavrakis Novice

          Maybe worth noting that I tried these two methods of adding certs into the default store. I assumed that the WebView would be accessing the same store. Neither of these worked.

           

          void ApplicationUI::addCustomCerts()
          {
               qDebug()<< "addCustomCerts()";
               QString certPath="/app/native/assets/certs/*.cer";
               QList<QSslCertificate> certsFromFile=QSslCertificate::fromPath(certPath, QSsl::Der, QRegExp::Wildcard);
               QSslSocket::addDefaultCaCertificates(certsFromFile);
          }
          void ApplicationUI::addCustomCerts()
          {
               qDebug()<< "addCustomCerts()";
               QString certPath="/app/native/assets/certs/*.cer";
               QList<QSslCertificate> certsFromFile=QSslCertificate::fromPath(certPath, QSsl::Der, QRegExp::Wildcard);
               QSslConfiguration sslConfig=QSslConfiguration::defaultConfiguration();
               QList<QSslCertificate> certs;
               certs.append(sslConfig.caCertificates());
               certs.append(certsFromFile);
               sslConfig.setCaCertificates(certs);
               QSslConfiguration::setDefaultConfiguration(sslConfig);
          }
  • Re: Using 10.3.2 API's?
    roger04 Expert

    On a side note, as libbbcascades.so in your SDK doesn't contains 10.3.2 functions (it's 10.3.1), I also needed to copy libbbcascades.so file from my Passport to retrieve the internal function names, which was located in

    file:///usr/lib/

     

     

    EDIT:

    Here's my libbbcascades.so file from my 10.3.2 Passport in case you want to play with it.

    MSOHM Edit - Have to remove download link to this file.

    • Re: Using 10.3.2 API's?
      tjmavrakis Novice
      Wow, thank you so much for your help! I will try this solution and post back here.

      I want to package two certificates in the assets directory and use them for the WebView. My app frequently loads up a website gfycat.com which gives certificate warnings that the user cannot bypass. There is no issue with the site's certificates though, instead it's an issue with BB10 OS outdated certificate store.

      If you have any more insight regarding this problem, I would love to hear it. My app is Reddit in Motion!
  • Re: Using 10.3.2 API's?
    roger04 Expert
    Reddit In Motion is a great app, congrats on bringing that app to BlackBerry 10 long time ago and still support it.

    I haven't tried the code I've shared with a real cert, let's hope it works. If you prefer to go the easy way, you can also install a cert on your user's phone by sending an invocation with the cert path as uri, something like this :
    /* coded on mobile, may contain syntax errors */
    InvokeRequest request;
    request.setUri("file://" + QDir::currentPath() + "/app/public/assets/myCert.cer");

    InvokeManager manager;
    manager.invoke(request);




    This code will result in a card like this one (sorry for not embedding an image, it's hard to do so on mobile) :
    https://s14.postimg.org/7b88a2btt/IMG_20161125_054155.png

    I might not have downloaded the right certificate, as even after installing it, I still get the cert warning when trying to access gfycat.com. The certificate used for taking this screenshot can be downloaded here :
    https://www.amazontrust.com/repository/

    I'll ping @MRGREEN, developer of multiCERT, to see if he has more info on this issue.
    • Re: Using 10.3.2 API's?
      tjmavrakis Novice
      Yes that was my plan B, but to a non-technical user importing a certificate might look a little scary! So i was hoping to do it behind the scenes if possible.

      That's the right place to get the certs, but you need two of them! Get the Amazon Root CA 1 and the Starfield Services Root. When you import both of those into your device's cert store, gfycat works just fine.
  • Re: Using 10.3.2 API's?
    roger04 Expert

    I've tried the setCertificatePath() trick here with a folder containing real certificates and it didn't worked, not sure why.

     

    I guess you won't have another choice than to ask your user to install the certs manually. I've created a sample project that does that, I also created a pem certificate that contains both certificates needed for gfycat.com, that way your users will only have one screen to import two certificates.

     

    After importing certificates, my WebView is able to access gfycat.com.

     

    Thanks for the challenging problem, it was fun to try to solve it, it doesn't end up as what you wanted but hope it will help your users to continue using Reddit In Motion.

     

    Sample project attached to this post, but here's the relevant code

     

    // main.qml
    
    import bb.cascades 1.2
    import bb.system 1.2
    
    Page {
        function onInstallCertsFinished() {
            webView.url = webView.lastUrlRequested
        }
    
        Container {
            WebView {
                id: webView
                property string lastUrlRequested
                
                url: "https://gfycat.com"
                
                onNavigationRequested:  lastUrlRequested = request.url
                onLoadingChanged: {
                    if (loadRequest.status == WebLoadStatus.Failed) {
                        if (lastUrlRequested.indexOf("gfycat.com") > -1) {
                            installCertsDialog.show()
                        }
                    }
                }
                
                attachedObjects: [
                    SystemDialog {
                        id: installCertsDialog
                        title: "Install certificates for gfycat.com?"
                        body: "gfycat.com certificates are missing on your device and needs to be imported, do you want to import them?"
                        onFinished: {
                            if (result == SystemUiResult.ConfirmButtonSelection) {
                                _app.installCertsFinished.connect(onInstallCertsFinished)
                                _app.installCerts()
                            }
                        }
                    }
                ]
            }
        }
    }
    // applicationui.cpp
    
    #include "applicationui.hpp"
    
    #include <bb/cascades/Application>
    #include <bb/cascades/QmlDocument>
    #include <bb/cascades/AbstractPane>
    
    #include <bb/system/InvokeManager>
    #include <bb/system/InvokeTargetReply>
    
    using namespace bb::cascades;
    using namespace bb::system;
    
    ApplicationUI::ApplicationUI() :
            QObject()
    {
        QmlDocument *qml = QmlDocument::create("asset:///main.qml").parent(this);
        qml->setContextProperty("_app", this);
        AbstractPane *root = qml->createRootObject<AbstractPane>();
        Application::instance()->setScene(root);
    }
    
    void ApplicationUI::installCerts() {
        InvokeRequest request;
        request.setUri("file://" + QDir::currentPath() + "/app/native/assets/certs/myCustomCerts.pem");
    
        InvokeManager* manager = new InvokeManager(this);
        InvokeTargetReply* reply = manager->invoke(request);
        connect(reply, SIGNAL(finished()), this, SLOT(onFinished()));
        connect(reply, SIGNAL(finished()), manager, SLOT(deleteLater()));
    }
    
    void ApplicationUI::onFinished() {
        InvokeTargetReply* reply = qobject_cast<InvokeTargetReply*>(sender());
        emit installCertsFinished();
        reply->deleteLater();
    }
    // applicationui.hpp
    
    #ifndef ApplicationUI_HPP_
    #define ApplicationUI_HPP_
    
    #include <QObject>
    
    class ApplicationUI : public QObject
    {
        Q_OBJECT
    public:
        ApplicationUI();
        virtual ~ApplicationUI() {}
    
        Q_INVOKABLE void installCerts();
    
    private slots:
        void onFinished();
    
    signals:
        void installCertsFinished();
    };
    
    #endif /* ApplicationUI_HPP_ */
    // .pro file
    
    LIBS += -lbbsystem