platform/bb/rhodes/src/rhomobile/RhodesApplication.java in rhodes-1.4.2 vs platform/bb/rhodes/src/rhomobile/RhodesApplication.java in rhodes-1.5.0

- old
+ new

@@ -22,48 +22,50 @@ import net.rim.device.api.browser.field.UrlRequestedEvent; import net.rim.device.api.io.http.HttpHeaders; import net.rim.device.api.system.Alert; import net.rim.device.api.system.Application; import net.rim.device.api.system.ApplicationManager; +import net.rim.device.api.system.Bitmap; import net.rim.device.api.system.Characters; +import net.rim.device.api.system.Display; +import net.rim.device.api.system.EncodedImage; import net.rim.device.api.system.KeyListener; import net.rim.device.api.system.SystemListener; //import javax.microedition.io.file.FileSystemListener; import net.rim.device.api.system.TrackwheelListener; import net.rim.device.api.ui.*; +import net.rim.device.api.ui.component.BitmapField; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.ui.component.Menu; import net.rim.device.api.ui.component.Status; +import net.rim.device.api.ui.container.FullScreen; import net.rim.device.api.ui.container.PopupScreen; import net.rim.device.api.ui.container.VerticalFieldManager; //import net.rim.device.api.ui.container.HorizontalFieldManager; import net.rim.device.api.ui.component.ButtonField; import net.rim.device.api.ui.component.LabelField; import net.rim.device.api.ui.Manager; +import net.rim.device.api.math.Fixed32; import javax.microedition.media.*; +//import net.rim.device.api.system.EventInjector.KeyCodeEvent; -import com.rho.Mutex; -import com.rho.RhoClassFactory; -import com.rho.RhoConf; -import com.rho.RhoEmptyLogger; -import com.rho.RhoEmptyProfiler; -import com.rho.RhoLogger; -import com.rho.RhoMainScreen; -import com.rho.RhoProfiler; -import com.rho.RhoRuby; -import com.rho.RhoThread; -import com.rho.SimpleFile; -import com.rho.Version; +import com.rho.*; //import com.rho.db.DBAdapter; -import com.rho.location.GeoLocation; +import com.rho.rubyext.GeoLocation; +import com.rho.net.NetResponse; import com.rho.net.RhoConnection; import com.rho.net.URI; import com.rho.sync.SyncThread; import com.rho.sync.ISyncStatusListener; import com.rho.Jsr75File; +import com.rho.RhodesApp; +import com.xruby.runtime.lang.RubyProgram; +import com.rho.net.NetResponse; +import net.rim.device.api.xml.parsers.SAXParser; + /** * */ final public class RhodesApplication extends UiApplication implements RenderingApplication, SystemListener, ISyncStatusListener//, FileSystemListener { @@ -94,10 +96,11 @@ LOG.INFO_OUT( "rootChanged. arg0 :" + arg0 + "arg1: " + arg1); if ( arg0 == FileSystemListener.ROOT_ADDED && arg1 != null && arg1.equals("SDCard/") ) m_bSDCardAdded = true; }*/ + //boolean m_bSkipKeyPress = false; class CKeyListener implements KeyListener{ public boolean keyChar(char key, int status, int time) { if( key == Characters.ENTER ) { @@ -105,16 +108,18 @@ openLink(); return true; } return false; } - public boolean keyDown(int keycode, int time) { int nKey = Keypad.key(keycode); if ( nKey == Keypad.KEY_ESCAPE ) { - back(); + /*if ( m_bSkipKeyPress ) + m_bSkipKeyPress = false; + else*/ + back(); return true; } return false; } @@ -148,11 +153,11 @@ navigateUrl(curUrl);*/ // } //} - +/* private String processAjaxCall(String request) { if (!request.startsWith(RHODES_AJAX_PROTOCOL)) return null; String command = request.substring(RHODES_AJAX_PROTOCOL.length()).trim(); Hashtable params = new Hashtable(); @@ -182,11 +187,11 @@ LOG.INFO(message); return null; } return null; - } + }*/ boolean isExternalUrl(String strUrl) { return strUrl.startsWith("http://") || strUrl.startsWith("https://"); } @@ -194,16 +199,12 @@ String canonicalizeURL( String url ){ if ( url == null || url.length() == 0 ) return ""; url.replace('\\', '/'); - if ( !url.startsWith(_httpRoot) && !isExternalUrl(url) ){ - if ( url.charAt(0) == '/' ) - url = _httpRoot.substring(0, _httpRoot.length()-1) + url; - else - url = _httpRoot + url; - } + if ( !url.startsWith(_httpRoot) && !isExternalUrl(url) ) + url = FilePath.join(_httpRoot,url); return url; } void navigateUrl(String url){ @@ -232,17 +233,45 @@ public void postUrl(String url, String body, HttpHeaders headers) { postUrl(url, body, headers, null); } - public void postUrl(String url, String body, HttpHeaders headers, Callback callback){ + public void postUrl(String url, String body, HttpHeaders headers, Runnable callback){ PrimaryResourceFetchThread thread = new PrimaryResourceFetchThread( canonicalizeURL(url), headers, body.getBytes(), null, callback); thread.setInternalRequest(true); thread.start(); } + public static class NetCallback + { + public NetResponse m_response; + + public void waitForResponse() + { + synchronized(this) + { + try{ this.wait(); }catch(InterruptedException exc){} + } + } + + public void setResponse(NetResponse resp) + { + synchronized(this) + { + m_response = resp; + this.notify(); + } + } + } + public void postUrlWithCallback(String url, String body, HttpHeaders headers, NetCallback netCallback){ + PrimaryResourceFetchThread thread = new PrimaryResourceFetchThread( + canonicalizeURL(url), headers, body.getBytes(), null); + thread.setNetCallback(netCallback); + thread.start(); + } + void saveCurrentLocation(String url) { if (RhoConf.getInstance().getBool("KeepTrackOfLastVisitedPage")) { RhoConf.getInstance().setString("LastVisitedPage",url); RhoConf.getInstance().saveToFile(); LOG.TRACE("Saved LastVisitedPage: " + url); @@ -302,11 +331,11 @@ if ( !strUrl.startsWith(_httpRoot) && !isExternalUrl(strUrl) ) strUrl = _httpRoot + (strUrl.startsWith("/") ? strUrl.substring(1) : strUrl); int nPos = -1; - for( int i = _history.size()-1; i >= 0; i-- ){ + for( int i = 0; i < _history.size(); i++ ){ if ( strUrl.equalsIgnoreCase((String)_history.elementAt(i)) ){ nPos = i; break; } /*String strUrl1 = strUrl + "/index"; @@ -489,17 +518,21 @@ private Vector _history; private final String _httpRoot = "http://localhost:8080/"; - private boolean _isFullBrowser = false; + private static boolean _isFullBrowser = false; private static PushListeningThread _pushListeningThread = null; private static RhodesApplication _instance; public static RhodesApplication getInstance(){ return _instance; } + private static RhodesApp RHODESAPP(){ return RhodesApp.getInstance(); } + + public static boolean isFullBrowser(){ return _isFullBrowser; } + /*************************************************************************** * Main. **************************************************************************/ public static void main(String[] args) { @@ -588,67 +621,80 @@ private static boolean m_bRubyInit = false; public void activate() { //DO NOT DO ANYTHING before doStartupWork doStartupWork(); + showSplashScreen(); LOG.TRACE("Rhodes start activate ***--------------------------***"); - if ( !m_bRubyInit ) - { - synchronized (m_eventRubyInit) { - try{ - m_eventRubyInit.wait(); - }catch(Exception e) - { - LOG.ERROR("wait failed", e); - } - } - } + UiApplication.getUiApplication().invokeLater(new Runnable() { + + public void run() { + if ( !m_bRubyInit ) + { + synchronized (m_eventRubyInit) { + try{ + m_eventRubyInit.wait(); + }catch(Exception e) + { + LOG.ERROR("wait failed", e); + } + } + } + + if ( !RhoRuby.rho_ruby_isValid() ) + { + LOG.ERROR("Cannot initialize Rho framework. Application will exit."); + Dialog.alert("Cannot initialize Rho framework. Application will exit. Log will send to log server."); + + RhoConf.sendLog(); + + System.exit(1); + } + + runActivateHooks(); + + RhoRuby.rho_ruby_activateApp(); + + if(!restoreLocation()) { + navigateHome(); + } + + LOG.TRACE("Rhodes end activate ***--------------------------***"); + } + + }); - if ( !RhoRuby.rho_ruby_isValid() ) - { - LOG.ERROR("Cannot initialize Ruby framework. Application will exit."); - Dialog.alert("Cannot initialize Ruby framework. Application will exit. Log will send to log server."); - - RhoConf.sendLog(); - - System.exit(1); - } - - runActivateHooks(); - - RhoRuby.rho_ruby_activateApp(); - - if(!restoreLocation()) { - navigateHome(); - } - - LOG.TRACE("Rhodes end activate ***--------------------------***"); - super.activate(); } - void initRuby() + void initRuby()throws Exception { - RhoRuby.RhoRubyStart(""); - SyncThread sync = null; - try{ - sync = SyncThread.Create( new RhoClassFactory() ); - - }catch(Exception exc){ - LOG.ERROR("Create sync failed.", exc); - } - if (sync != null) { - sync.setStatusListener(this); - } - - RhoRuby.RhoRubyInitApp(); - - m_bRubyInit = true; - synchronized (m_eventRubyInit) { - m_eventRubyInit.notifyAll(); - } + try + { + RhoRuby.RhoRubyStart(""); + + SyncThread sync = null; + + try{ + sync = SyncThread.Create( new RhoClassFactory() ); + + }catch(Exception exc){ + LOG.ERROR("Create sync failed.", exc); + } + if (sync != null) { + sync.setStatusListener(this); + } + + RhoRuby.RhoRubyInitApp(); + }finally + { + m_bRubyInit = true; + synchronized (m_eventRubyInit) { + m_eventRubyInit.notifyAll(); + } + } } public void deactivate() { LOG.TRACE("Rhodes deactivate ***--------------------------***"); @@ -676,10 +722,15 @@ //} else invokeLater( new Runnable() { public void run() { if (_syncStatusPopup != null) { _syncStatusPopup.showStatus(_lastStatusMessage); + }else + { + SyncStatusPopup popup = new SyncStatusPopup(_lastStatusMessage); + RhodesApplication.getInstance().setSyncStatusPopup(popup); + pushScreen(popup); } } }); } @@ -984,10 +1035,68 @@ public MenuItem getSavedGetLinkItem() { return savedGetLinkItem; } } + public void showSplashScreen() + { + SplashScreen splash = RHODESAPP().getSplashScreen(); + + InputStream is = null; + try { + RubyProgram obj = new xruby.version.main(); + String pngname = "/apps/app/loading.png"; + is = obj.getClass().getResourceAsStream(pngname); + if ( is != null ) + { + int size = is.available(); + byte[] data = new byte[size]; + for (int offset = 0; offset < size;) { + int n = is.read(data, offset, size - offset); + if (n < 0) + break; + offset += n; + } + EncodedImage img = EncodedImage.createEncodedImage(data, 0, size); + long nFlags = 0; + if (splash.isFlag(SplashScreen.HCENTER) ) + nFlags |= Field.FIELD_HCENTER; + if (splash.isFlag(SplashScreen.VCENTER) ) + nFlags |= Field.FIELD_VCENTER; + + int scaleX = 1, scaleY = 1; + int currentWidthFixed32 = Fixed32.toFP(img.getWidth()); + int currentHeightFixed32 = Fixed32.toFP(img.getHeight()); + int screenWidthFixed32 = Fixed32.toFP(Display.getWidth()); + int screenHeightFixed32 = Fixed32.toFP(Display.getHeight()); + + if (splash.isFlag(SplashScreen.VZOOM) ) + scaleY = Fixed32.div(currentHeightFixed32, screenHeightFixed32); + if (splash.isFlag(SplashScreen.HZOOM) ) + scaleX = Fixed32.div(currentWidthFixed32, screenWidthFixed32); + + EncodedImage img2 = img; + if ( scaleX != 1 || scaleY != 1) + img2 = img.scaleImage32(scaleX, scaleY); + Bitmap bitmap = img2.getBitmap(); + + splash.start(); + BitmapField imageField = new BitmapField(bitmap, nFlags); + _mainScreen.deleteAll(); + _mainScreen.add(imageField); + } + } + catch (Exception e) { + LOG.ERROR("Can't show splash screen", e); + }finally + { + if ( is != null ) + try{is.close();}catch(IOException exc){} + is = null; + } + } + public void showLogScreen() { LogScreen screen = new LogScreen(); //Push this screen to display it to the user. UiApplication.getUiApplication().pushScreen(screen); @@ -1029,10 +1138,12 @@ RhoLogger.InitRhoLog(); LOG.INFO(" STARTING RHODES: ***----------------------------------*** " ); + RhodesApp.Create(RhoConf.getInstance().getRhoRootPath()); + CKeyListener list = new CKeyListener(); CTrackwheelListener wheel = new CTrackwheelListener(); this._history = new Vector(); //SyncEngine.setNotificationImpl( new SyncNotificationsImpl() ); @@ -1047,29 +1158,37 @@ _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.JAVASCRIPT_ENABLED, true); _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.JAVASCRIPT_LOCATION_ENABLED, true); _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.ENABLE_CSS, true); _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.DEFAULT_CHARSET_VALUE, "utf-8"); _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.OVERWRITE_CHARSET_MODE, true); + _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.ALLOW_POPUPS, true); + _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.USE_BACKGROUND_IMAGES, true); +// _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.VALUE_THRESHOLD, 100000); + + // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.USE_BACKGROUND_IMAGES, true); // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.SHOW_IMAGE_PLACEHOLDERS, false); // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.ENABLE_WML, false); // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.ENABLE_EMBEDDED_RICH_CONTENT, false); // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.ENABLE_IMAGE_EDITING, false); // _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, RenderingOptions.NO_SEARCH_MENU_MODE, true); - - if ( RhoConf.getInstance().getBool("use_bb_full_browser") ) + if ( RhoConf.getInstance().getString("use_bb_full_browser").equalsIgnoreCase("touch") ) + _isFullBrowser = _mainScreen.isTouchScreen(); + else if ( RhoConf.getInstance().getBool("use_bb_full_browser") ) { Version.SoftVersion ver = Version.getSoftVersion(); if ( ver.nMajor > 4 || ( ver.nMajor == 4 && ver.nMinor >= 6 ) ) - { - //this is the undocumented option to tell the browser to use the 4.6 Rendering Engine - _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, 17000, true); _isFullBrowser = true; - } } + + if (_isFullBrowser) + { + //this is the undocumented option to tell the browser to use the 4.6 Rendering Engine + _renderingSession.getRenderingOptions().setProperty(RenderingOptions.CORE_OPTIONS_GUID, 17000, true); + } // _pushListeningThread = new PushListeningThread(); // _pushListeningThread.start(); try { @@ -1174,35 +1293,33 @@ try { browserContent = _renderingSession.getBrowserContent(connection, this, e); if (browserContent != null) { - + browserContent.finishLoading(); + Field field = browserContent.getDisplayableContent(); if (field != null) { + + RHODESAPP().getSplashScreen().hide(); + synchronized (Application.getEventLock()) { _mainScreen.deleteAll(); _mainScreen.add(field); +/* + _mainScreen.doPaint(); + if ( e == null ) + {//This should awake screen in case of long network response + KeyCodeEvent inject1 = new KeyCodeEvent( KeyCodeEvent.KEY_DOWN, (char)Keypad.KEY_ESCAPE, 0); + KeyCodeEvent inject2 = new KeyCodeEvent( KeyCodeEvent.KEY_UP, (char)Keypad.KEY_ESCAPE, 0); + inject1.post(); + inject2.post(); + m_bSkipKeyPress = true; + }*/ } } - - if ( _isFullBrowser ) - browserContent.finishLoading(); - else - { - if ( URI.isLocalHost(connection.getURL()) ) - { - synchronized (Application.getEventLock()) - //synchronized (getAppEventLock()) - { - browserContent.finishLoading(); - } - }else - browserContent.finishLoading(); - } } - } catch (RenderingException re) { } finally { SecondaryResourceFetchThread.doneAddingImages(); } @@ -1306,18 +1423,18 @@ // TODO: close the application break; case Event.EVENT_SET_HEADER : case Event.EVENT_SET_HTTP_COOKIE : { - String cookie = ((SetHttpCookieEvent)event).getCookie(); + /*String cookie = ((SetHttpCookieEvent)event).getCookie(); String response = processAjaxCall(cookie); if (response != null) synchronized (pendingResponses) { pendingResponses.addElement(response); } response = null; - cookie = null; + cookie = null;*/ break; } case Event.EVENT_HISTORY : // no history support case Event.EVENT_EXECUTING_SCRIPT : // no progress bar is supported case Event.EVENT_FULL_WINDOW : // no full window support @@ -1393,11 +1510,11 @@ HttpConnection connection = Utilities.makeConnection(url, resource.getRequestHeaders(), null); return connection; } else { - if ( URI.isLocalHost(url) ) + if ( URI.isLocalHost(url) || URI.isLocalData(url)) { HttpConnection connection = Utilities.makeConnection(url, resource.getRequestHeaders(), null); return connection; }else { @@ -1442,20 +1559,23 @@ //wait(80); try{ _application.initRuby(); - _pushListeningThread = new PushListeningThread(); - _pushListeningThread.start(); }catch(Exception e) { - LOG.ERROR("HttpServerThread failed.", e); + LOG.ERROR("initRuby failed.", e); + return; }catch(Throwable exc) { - LOG.ERROR("HttpServerThread crashed.", exc); + LOG.ERROR("initRuby crashed.", exc); + return; } - + + _pushListeningThread = new PushListeningThread(); + _pushListeningThread.start(); + while( !m_bExit ) { while(!m_stackCommands.isEmpty()) { PrimaryResourceFetchThread oCmd = null; @@ -1494,48 +1614,55 @@ }; private static HttpServerThread m_oFetchThread; private static RhodesApplication _application; - private static Callback _callback; + private static Runnable _callback; private Event _event; private byte[] _postData; private HttpHeaders _requestHeaders; private String _url; private boolean m_bInternalRequest = false; private boolean m_bActivateApp = false; + NetCallback m_netCallback; public void setInternalRequest(boolean b) { m_bInternalRequest = b; } public PrimaryResourceFetchThread(String url, HttpHeaders requestHeaders, byte[] postData, - Event event) { - + Event event) + { _url = url; _requestHeaders = requestHeaders; _postData = postData; _event = event; //_callback = null; } public PrimaryResourceFetchThread(String url, HttpHeaders requestHeaders, byte[] postData, - Event event, Callback callback) { - + Event event, Runnable callback) + { _url = url; _requestHeaders = requestHeaders; _postData = postData; _event = event; if ( callback != null ) _callback = callback; } + public void setNetCallback(NetCallback netCallback) + { + m_netCallback = netCallback; + m_bInternalRequest = true; + } + public PrimaryResourceFetchThread(boolean bActivateApp) { m_bActivateApp = bActivateApp; } static void Create(RhodesApplication app) @@ -1571,10 +1698,21 @@ HttpConnection connection = Utilities.makeConnection(_url, _requestHeaders, _postData); if ( m_bInternalRequest ) { try{ - connection.getResponseCode(); + + int nRespCode = connection.getResponseCode(); + + if ( m_netCallback != null ) + { + InputStream is = connection.openInputStream(); + byte[] buffer = new byte[is.available()]; + is.read(buffer); + + String strRespBody = new String(buffer); + m_netCallback.setResponse( new NetResponse(strRespBody, nRespCode) ); + } }catch(IOException exc) { LOG.ERROR("Callback failed: " + _url, exc); } }