javaruntimes/midp/runtime/src.s60/platformrequesthandler.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:23:59 +0300
branchRCL_3
changeset 83 26b2b12093af
parent 60 6c158198356e
permissions -rw-r--r--
Revision: v2.2.17 Kit: 201041

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  This class provides container for message.
*
*/


#include <memory>

#ifdef RD_JAVA_S60_RELEASE_10_1_ONWARDS
#include <SchemeHandler.h>
#else
#include <schemehandler.h>
#endif

#include <apgcli.h>               // for RApaLsSession
#include <apacmdln.h>
#include <sstream>

#include "platformrequesthandler.h"

#include "javasymbianoslayer.h"
#include "javacommonutils.h"
#include "s60commonutils.h"
#include "exceptionbase.h"
#include "logger.h"

using namespace java::runtime;
using namespace java::util;


PlatformRequestInterface* getPlatformRequestHandlerObj()
{
    JELOG2(EJavaRuntime);
    return new PlatformRequestHandler();
}

/**
 *
 */
PlatformRequestHandler::PlatformRequestHandler()
{
}

/**
 *
 */
PlatformRequestHandler::~PlatformRequestHandler()
{
}

/**
 * handleUri() supports at least following URIs:
 * file://, http://, https://, rtsp://, mailto://, wtai:, tel:, vtel:,
 * mms:, cti:, javaapp: and localapp:
 */
void PlatformRequestHandler::handleUri(const std::wstring& aUri)
{
    JELOG2(EJavaRuntime);
    TRAPD(err,launchAppL(aUri););
    if (err != KErrNone)
    {
        ELOG1(EJavaRuntime, "ERROR!!! PlatformRequestHandler::handleUri() %d",
              err);
        if (KErrNotFound == err)
        {
            if ((aUri.find(L"localapp:jam/launch?") == 0) ||
                    (aUri.find(L"localapp://jam/launch?") == 0) ||
                    (aUri.find(L"javaapp:") == 0))
            {
                // The URI is supported but the MIDlet specified by the URI
                // does not exist.
                throw ExceptionBase(PlatformRequestInterface::UNEXPECTED_ERROR,
                                    "Cannot start Java application",__FILE__,__FUNCTION__,__LINE__);
            }

            throw ExceptionBase(PlatformRequestInterface::CONNECTION_NOT_SUPPORTED,
                                "Not supported URI",__FILE__,__FUNCTION__,__LINE__);
        }
        else
        {
            std::string errTxt("Execution PlatformRequestHandler::handleUri() "
                               "failed to following error: ");
            errTxt.append(java::util::JavaCommonUtils::intToString(err));
            throw ExceptionBase(PlatformRequestInterface::UNEXPECTED_ERROR,
                                errTxt,__FILE__,__FUNCTION__,__LINE__);
        }
    }
}

/**
 *
 */
void PlatformRequestHandler::launchAppL(const std::wstring& aUri)
{
    JELOG2(EJavaRuntime);
    LOG1(EJavaRuntime, EInfo, "Platform request. URI: %S", aUri.c_str());
    if (startsArbitraryNativeApp(aUri))
    {
        launchNativeAppL(aUri);
    }
    else
    {
        TPtrC ptr((const TUint16 *)aUri.c_str(), aUri.length());
        std::auto_ptr<CSchemeHandler> schemeHandler(CSchemeHandler::NewL(ptr));
        schemeHandler->HandleUrlStandaloneL(); // Process Uri in standalone mode.
    }
}

/**
 *
 */
bool PlatformRequestHandler::startsArbitraryNativeApp(const std::wstring& aUri)
{
    if (aUri.find(L"nativeapp:") == 0)
    {
        return true;
    }

    if (aUri.find(L"localapp:native/launch?") == 0 ||
            aUri.find(L"localapp://native/launch?") == 0)
    {
        return true;
    }

    return false;
}

/**
 *
 */
void PlatformRequestHandler::launchNativeAppL(const std::wstring& aUri)
{
    std::wstring appName;

    RApaLsSession apaSession;
    TInt err = apaSession.Connect();
    User::LeaveIfError(err);
    CleanupClosePushL(apaSession);

    // Support percent encoding in the URI
    std::wstring uri = JavaCommonUtils::percentDecode(aUri);

    // Start by by Uid?
    const std::wstring appUid(L"application-uid=");
    const std::wstring appExe(L"application-exe=");
    const std::wstring semiColon(L";");
    std::string::size_type idx = uri.find(appUid);
    std::string::size_type idxSemiColon;
    if (idx != std::string::npos)
    {
        // Parse Uid
        TUid uid;
        idx += appUid.size(); // skip argument name
        idxSemiColon = uri.find(semiColon, idx);
        if (idxSemiColon == std::string::npos)
        {
            idxSemiColon = uri.size();
        }
        std::wstring wstrUid = uri.substr(idx, (idxSemiColon - idx));

        LOG1(EJavaRuntime, EInfo,
             "PlatformRequestHandler: launchNativeAppL: Uid in req is : %S", wstrUid.c_str());

        long long tmpInt;
        std::wstringstream stream(wstrUid);
        if (wstrUid.find(L"0x") == 0 || wstrUid.find(L"0X") == 0)
        {
            // hexadecimal
            stream >> std::hex >> tmpInt;
        }
        else
        {
            stream >> tmpInt;
        }
        uid.iUid = tmpInt;

        // Find executable name from AppArc
        TApaAppInfo info;
        err = apaSession.GetAppInfo(info, uid);
        if (KErrNone != err)
        {
            ELOG2(EJavaRuntime,
                  "PlatformRequestHandler: launchNativeAppL: GetAppInfo for uid %x failed, err %d",
                  uid.iUid,
                  err);
            User::Leave(err);
        }
        info.iFullName.Append('\0');
        appName = (wchar_t *)(&(info.iFullName[0]));
        LOG1(EJavaRuntime, EInfo,
             "PlatformRequestHandler: launchNativeAppL: app to start is : %S", appName.c_str());
    }
    else if ((idx = uri.find(appExe)) != std::string::npos)
    {
        // Parse exe name
        idx += appExe.size(); // skip argument name
        idxSemiColon = uri.find(semiColon, idx);
        if (idxSemiColon == std::string::npos)
        {
            idxSemiColon = uri.size();
        }
        appName = uri.substr(idx, (idxSemiColon - idx));

        LOG1(EJavaRuntime, EInfo,
             "PlatformRequestHandler: launchNativeAppL: Exe name in req is : %S", appName.c_str());
    }
    else
    {
        // Illegal uri
        User::Leave(KErrArgument);
    }

    // Start forming command line
    CApaCommandLine* cmdLine = CApaCommandLine::NewLC();

    // Set executable name
    HBufC *pAppName = S60CommonUtils::wstringToDes(appName.c_str());
    if (pAppName)
    {
        CleanupStack::PushL(pAppName);
        cmdLine->SetExecutableNameL(*pAppName);
        CleanupStack::PopAndDestroy(pAppName);
    }
    cmdLine->SetCommandL(EApaCommandRun);

    // Content (document) specified?
    const std::wstring contentArg(L"content=");
    if ((idx = uri.find(contentArg)) != std::string::npos)
    {
        // Parse document name
        idx += contentArg.size(); // skip argument name
        idxSemiColon = uri.find(semiColon, idx);
        if (idxSemiColon == std::string::npos)
        {
            idxSemiColon = uri.size();
        }
        std::wstring content = uri.substr(idx, (idxSemiColon - idx));

        LOG1(EJavaRuntime, EInfo,
             "PlatformRequestHandler: launchNativeAppL: content: %S", content.c_str());

        HBufC *pContent = S60CommonUtils::wstringToDes(content.c_str());
        if (pContent)
        {
            CleanupStack::PushL(pContent);
            cmdLine->SetDocumentNameL(*pContent);
            CleanupStack::PopAndDestroy(pContent);
        }
    }

    // Other application arguments specified?
    const std::wstring appArgs(L"application-args=");
    if ((idx = uri.find(appArgs)) != std::string::npos)
    {
        // Parse applications args
        idx += appArgs.size(); // skip argument name
        // Rest of the command URI contains args
        idxSemiColon = uri.size();
        std::wstring args = uri.substr(idx, (idxSemiColon - idx));

        LOG1(EJavaRuntime, EInfo,
             "PlatformRequestHandler: launchNativeAppL: app args: %S", args.c_str());

        if (args.size() > 0)
        {
            // Convert args to 8 bit descriptor
            char* utf8string = NULL;
            try
            {
                utf8string = JavaCommonUtils::wstringToUtf8(args);
            }
            catch (std::exception& e)
            {
                ELOG1(EJavaRuntime,
                      "PlatformRequestHandler: launchNativeAppL: Cannot convert app args to"
                      " UTF-8. Error %s", e.what());
                User::Leave(KErrArgument);
            }
            TInt argsLen = strlen(utf8string);
            TPtr8 ptrArgs((unsigned char *)utf8string, argsLen, argsLen + 4);

            cmdLine->SetTailEndL(ptrArgs);
            delete[] utf8string;
        }
    }

    // Start executable
    err = apaSession.StartApp(*cmdLine);
    if (KErrNone != err)
    {
        ELOG1(EJavaRuntime,
              "PlatformRequestHandler: launchNativeAppL: StartApp error %d", err);
        User::Leave(err);
    }

    CleanupStack::PopAndDestroy(cmdLine);
    CleanupStack::PopAndDestroy(); // apaSession
}