javaruntimes/midp/runtime/javasrc/javax/microedition/midlet/MIDlet.java
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package javax.microedition.midlet;
       
    20 
       
    21 import java.util.Hashtable;
       
    22 import javax.microedition.io.ConnectionNotFoundException;
       
    23 
       
    24 import com.nokia.mj.impl.rt.ui.ConfirmData;
       
    25 import com.nokia.mj.impl.rt.ui.RuntimeUi;
       
    26 import com.nokia.mj.impl.rt.ui.RuntimeUiFactory;
       
    27 
       
    28 import com.nokia.mj.impl.rt.support.ApplicationInfo;
       
    29 
       
    30 import com.nokia.mj.impl.security.midp.authorization.AccessControllerFactoryImpl;
       
    31 import com.nokia.mj.impl.security.midp.authorization.AccessControllerImpl;
       
    32 import com.nokia.mj.impl.security.utils.SecurityPromptMessage;
       
    33 
       
    34 import com.nokia.mj.impl.utils.Logger;
       
    35 
       
    36 /**
       
    37  * A class to be extended by the MIDlet applcation. See MIDP spec for
       
    38  * further details.
       
    39  *
       
    40  * @author Nokia Corporation
       
    41  * @version $Rev$
       
    42  */
       
    43 public abstract class MIDlet
       
    44 {
       
    45 
       
    46     /**
       
    47      * MidletApplication object is used to delegate and propagate the
       
    48      * life cycle tasks between the MIDlet application and the life cycle
       
    49      * of the MIDP runtime.
       
    50      */
       
    51     private MidletApplication mMidletApplication;
       
    52 
       
    53     private static Hashtable mNetworkPromptSchemes = null;
       
    54     private static Hashtable mNoPromptSchemes = null;
       
    55 
       
    56     /**
       
    57      * For allowing of MIDlet constructor to be called only once.
       
    58      */
       
    59     private static boolean mConstructionAllowed = true;
       
    60 
       
    61     /*** ----------------------------- PUBLIC ------------------------------ */
       
    62 
       
    63     /**
       
    64      * For checking if MIDlet is allowed to do some protected action.
       
    65      * @see MIDP spec for further details.
       
    66      * @param permission The permsission to be checked.
       
    67      * @return 0 if denied, 1 if allowed, -1 if unknown.
       
    68      */
       
    69     public final int checkPermission(String permission)
       
    70     {
       
    71         try
       
    72         {
       
    73             ApplicationInfo appInfo = ApplicationInfo.getInstance();
       
    74             AccessControllerImpl accessControllerImpl =
       
    75                 AccessControllerFactoryImpl.
       
    76                 getAccessController(appInfo.getSuiteUid(),
       
    77                                     appInfo.getName());
       
    78             return accessControllerImpl.checkPermission(permission);
       
    79         }
       
    80         catch (Throwable t)
       
    81         {
       
    82         }
       
    83         return 0;
       
    84     }
       
    85 
       
    86     /**
       
    87      * For informing the life cycle that the MIDlet wants to close itself.
       
    88      * @see MIDP spec for further details.
       
    89      */
       
    90     public final void notifyDestroyed()
       
    91     {
       
    92         mMidletApplication.notifyDestroyed();
       
    93     }
       
    94 
       
    95     /**
       
    96      * For informing the life cycle that the MIDlet wants to enter into
       
    97      * paused state.
       
    98      * @see MIDP spec for further details.
       
    99      */
       
   100     public final void notifyPaused()
       
   101     {
       
   102         mMidletApplication.notifyPaused();
       
   103     }
       
   104 
       
   105     /**
       
   106      * For informing the life cycle that the MIDlet resume from paused state
       
   107      * into active state.
       
   108      * @see MIDP spec for further details.
       
   109      */
       
   110     public final void resumeRequest()
       
   111     {
       
   112         mMidletApplication.resumeRequest();
       
   113     }
       
   114 
       
   115     /**
       
   116      * For getting application property defined in the manifest file and
       
   117      * in the JAD file (if present).
       
   118      * @see MIDP spec for further details.
       
   119      * @param key The name of the attribute.
       
   120      * @return The value of the attribute if found, otherwise null.
       
   121      */
       
   122     public final String getAppProperty(String key)
       
   123     {
       
   124         if (key == null)
       
   125         {
       
   126             throw new NullPointerException(
       
   127                 "MIDlet.getAppProperty() called with null key");
       
   128         }
       
   129         return mMidletApplication.getAppProperty(key);
       
   130     }
       
   131 
       
   132     /**
       
   133      * For doing the platform reguest. The implementation doesn't support
       
   134      * cancelling the pending requests.
       
   135      * @see MIDP spec for further details.
       
   136      * @param url The url for the platform request.
       
   137      * @return Always false, since there is no need to close the suite.
       
   138      */
       
   139     public final boolean platformRequest(String url)
       
   140     throws ConnectionNotFoundException
       
   141     {
       
   142         Logger.PLOG(Logger.EJavaRuntime,
       
   143                     "MIDlet.platformRequest(): " + url);
       
   144         if (null == url)
       
   145         {
       
   146             throw new NullPointerException(
       
   147                 "URL is null");
       
   148         }
       
   149         url = url.trim();
       
   150 
       
   151         // Empty string means cancel request.
       
   152         // Because we don't queue requests, no action taken here.
       
   153         if (true == url.equals(""))
       
   154         {
       
   155             return false;
       
   156         }
       
   157 
       
   158         // If the platform request is used to start arbitrary native application,
       
   159         // check that MIDlet is in manufacturer or operator domain
       
   160         if (startsArbitraryNativeApp(url))
       
   161         {
       
   162             ApplicationInfo appInfo = ApplicationInfo.getInstance();
       
   163             String domain = appInfo.getProtectionDomain();
       
   164             if ((ApplicationInfo.MANUFACTURER_DOMAIN.equals(domain) != true) &&
       
   165                     (ApplicationInfo.OPERATOR_DOMAIN.equals(domain) != true))
       
   166             {
       
   167                 Logger.WLOG(Logger.EJavaRuntime,
       
   168                             "Only manufacturer or operator domain MIDlets can start arbitrary native apps.");
       
   169 
       
   170                 throw new ConnectionNotFoundException(
       
   171                     "Request allowed only for manufacturer or operator MIDlets");
       
   172             }
       
   173         }
       
   174 
       
   175 
       
   176         Logger.ILOG(Logger.EJavaRuntime,
       
   177                     "Before handleConfirmationNote()");
       
   178 
       
   179         // Ask from the user if it is allowed to do the request.
       
   180         boolean acceptByUser = handleConfirmationNote(url);
       
   181         Logger.ILOG(Logger.EJavaRuntime,
       
   182                     "After handleConfirmationNote(): " + acceptByUser);
       
   183         if (false == acceptByUser)
       
   184         {
       
   185             throw new ConnectionNotFoundException("Request was cancelled by user");
       
   186         }
       
   187 
       
   188         // Do the request.
       
   189         _managePlatformRequest(url);
       
   190         return false;
       
   191     }
       
   192 
       
   193 
       
   194     /*** ---------------------------- PROTECTED --------------------------- */
       
   195 
       
   196     /**
       
   197      * The constructor of the MIDlet. It is possible to call this method only
       
   198      * by the MIDP life cycle and it can be done only once.
       
   199      * If the constructor of the subclass throws an exception, it will lead to
       
   200      * application start error dialog.
       
   201      * @see MIDP spec for further details.
       
   202      */
       
   203     protected MIDlet()
       
   204     {
       
   205         // Allow constructing of the MIDlet class only once.
       
   206         if (!mConstructionAllowed)
       
   207         {
       
   208             throw new SecurityException("Only application management "+
       
   209                                         "software is allowed to construct MIDlet");
       
   210         }
       
   211         mConstructionAllowed = false;
       
   212 
       
   213         // For communication between MIDlet and the MIDP life cycle.
       
   214         mMidletApplication = new MidletApplication(this);
       
   215         Logger.ILOG(Logger.EJavaRuntime,
       
   216                     "MIDlet created: " + this);
       
   217     }
       
   218 
       
   219     /**
       
   220      * The MIDP life cycle informs that it wants to close the MIDlet.
       
   221      * The unconditional is always true and any thrown exceptions will
       
   222      * be ignored.
       
   223      * @see MIDP spec for further details.
       
   224      * @param unconditional Always true.
       
   225      */
       
   226     protected abstract void destroyApp(boolean unconditional)
       
   227     throws MIDletStateChangeException;
       
   228 
       
   229     /**
       
   230      * The MIDP life cycle informs that it wants to start the MIDlet.
       
   231      * Any thrown exception will lead to application start error dialog.
       
   232      * @see MIDP spec for further details.
       
   233      */
       
   234     protected abstract void startApp() throws MIDletStateChangeException;
       
   235 
       
   236     /**
       
   237      * The MIDP life cycle informs that it wants to start the MIDlet.
       
   238      * This is never called by the implementation.
       
   239      * @see MIDP spec for further details.
       
   240      */
       
   241     protected abstract void pauseApp();
       
   242 
       
   243     /*** ----------------------------- PRIVATE ---------------------------- */
       
   244 
       
   245     /**
       
   246      * @return 'true' is returned in following situations:
       
   247      *         - confirmation query does not need to show or if user.
       
   248      *         - confirmation query has been shown to the user and user
       
   249      *           has selected 'Allow'.
       
   250      */
       
   251     private boolean handleConfirmationNote(String url)
       
   252     throws ConnectionNotFoundException
       
   253     {
       
   254         ApplicationInfo appInfo = ApplicationInfo.getInstance();
       
   255         String domain = appInfo.getProtectionDomain();
       
   256         if ((ApplicationInfo.MANUFACTURER_DOMAIN.equals(domain) == true) ||
       
   257                 (ApplicationInfo.OPERATOR_DOMAIN.equals(domain) == true))
       
   258         {
       
   259             return true;
       
   260         }
       
   261 
       
   262         if ((mNetworkPromptSchemes == null) ||
       
   263                 (mNoPromptSchemes == null))
       
   264         {
       
   265             fillSchemes();
       
   266         }
       
   267 
       
   268         String scheme = getScheme(url);
       
   269         String appName = appInfo.getName();
       
   270         String namedPermission = (String)mNetworkPromptSchemes.get(scheme);
       
   271         if (namedPermission != null)
       
   272         {
       
   273             AccessControllerImpl accessControllerImpl =
       
   274                 AccessControllerFactoryImpl.
       
   275                 getAccessController(appInfo.getSuiteUid(),
       
   276                                     appInfo.getName());
       
   277             return accessControllerImpl.isPermissionAllowed(namedPermission);
       
   278         }
       
   279         if (mNoPromptSchemes.containsKey(scheme) == true)
       
   280         {
       
   281             return true;
       
   282         }
       
   283         return showNote(appName,
       
   284                         SecurityPromptMessage.QUESTION_ID_APP_LAUNCH_VIA_PLAT_REQ);
       
   285     }
       
   286 
       
   287 
       
   288     private boolean showNote(String aAppName,String aConfirmationQueryId)
       
   289     {
       
   290         SecurityPromptMessage msg = SecurityPromptMessage.getInstance();
       
   291         String queryTxt = msg.getText(aConfirmationQueryId,null);
       
   292         String[] buttons = new String[2];
       
   293         buttons[0] = msg.getText(SecurityPromptMessage.ANSWER_ID_ALLOW,null);
       
   294         buttons[1] = msg.getText(SecurityPromptMessage.ANSWER_ID_DENY,null);
       
   295         ConfirmData dataObj = new ConfirmData(queryTxt,buttons,0);
       
   296 
       
   297         RuntimeUi uiObj = RuntimeUiFactory.getRuntimeUi();
       
   298         boolean isUserAnswered = uiObj.confirm(aAppName,dataObj);
       
   299         if (isUserAnswered == false)
       
   300         {
       
   301             return false;
       
   302         }
       
   303         int indexToChosenButton = dataObj.getAnswer();
       
   304         if (indexToChosenButton == 0)
       
   305         {
       
   306             return true;
       
   307         }
       
   308         return false;
       
   309     }
       
   310 
       
   311     private void fillSchemes()
       
   312     {
       
   313         if (mNetworkPromptSchemes == null)
       
   314         {
       
   315             mNetworkPromptSchemes = new Hashtable();
       
   316             mNetworkPromptSchemes.put("http:","javax.microedition.io.Connector.http");
       
   317             mNetworkPromptSchemes.put("https:","javax.microedition.io.Connector.https");
       
   318         }
       
   319         if (mNoPromptSchemes == null)
       
   320         {
       
   321             // These schemes start applications that ask user for
       
   322             // confirmation before any real action is done.
       
   323             mNoPromptSchemes = new Hashtable();
       
   324             mNoPromptSchemes.put("cti:","");
       
   325             mNoPromptSchemes.put("mailto:","");
       
   326             mNoPromptSchemes.put("mms:","");
       
   327             mNoPromptSchemes.put("mmsto:","");
       
   328             mNoPromptSchemes.put("rtsp:","");
       
   329             mNoPromptSchemes.put("sms:","");
       
   330             mNoPromptSchemes.put("tel:","");
       
   331         }
       
   332     }
       
   333 
       
   334     private String getScheme(String uri)
       
   335     throws ConnectionNotFoundException
       
   336     {
       
   337         int index = uri.indexOf(':');
       
   338         if (index == -1)
       
   339         {
       
   340             throw new ConnectionNotFoundException("Incorrect URI: " + uri);
       
   341         }
       
   342         index++;
       
   343         if (uri.length() <= index)
       
   344         {
       
   345             throw new ConnectionNotFoundException("Incorrect URI: " + uri);
       
   346         }
       
   347         return uri.substring(0,index);
       
   348     }
       
   349 
       
   350     private boolean startsArbitraryNativeApp(String uri)
       
   351     {
       
   352         // schemes are case sensitive
       
   353         if (uri.startsWith("nativeapp:"))
       
   354         {
       
   355             return true;
       
   356         }
       
   357 
       
   358         if (uri.startsWith("localapp:native/launch?") ||
       
   359                 uri.startsWith("localapp://native/launch?"))
       
   360         {
       
   361             return true;
       
   362         }
       
   363 
       
   364         return false;
       
   365     }
       
   366 
       
   367     /*** ----------------------------- NATIVE ----------------------------- */
       
   368 
       
   369     private native void _managePlatformRequest(String url);
       
   370 }