@Override public synchronized void handleMessage( String event, NativeJSObject message, org.mozilla.gecko.util.EventCallback callback) { try { switch (event) { case MESSAGE_LOAD: { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } final String classname = message.getString("classname"); final String filename = message.getString("filename"); final EventDispatcherImpl dispatcher = registerNewInstance(classname, filename); callback.sendSuccess(dispatcher.guid); } break; case MESSAGE_UNLOAD: { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } final String guid = message.getString("guid"); final EventDispatcherImpl dispatcher = mGUIDToDispatcherMap.remove(guid); if (dispatcher == null) { Log.w( LOGTAG, "Attempting to unload addon with unknown associated dispatcher; ignoring."); callback.sendSuccess(false); } dispatcher.unregisterAllEventListeners(); callback.sendSuccess(true); } break; } } catch (Exception e) { Log.e(LOGTAG, "Exception handling message [" + event + "]", e); if (callback != null) { callback.sendError("Exception handling message [" + event + "]: " + e.toString()); } } }
// This function only works for IPv4 private void getWifiIPAddress(final EventCallback callback) { final WifiManager mgr = (WifiManager) GeckoAppShell.getApplicationContext().getSystemService(Context.WIFI_SERVICE); if (mgr == null) { callback.sendError("Cannot get WifiManager"); return; } final WifiInfo info = mgr.getConnectionInfo(); if (info == null) { callback.sendError("Cannot get connection info"); return; } int ip = info.getIpAddress(); if (ip == 0) { callback.sendError("Cannot get IPv4 address"); return; } callback.sendSuccess(Formatter.formatIpAddress(ip)); }
/** * Opens a URI without any valid handlers on device. In the best case, a package is specified and * we can bring the user directly to the application page in an app market. If a package is not * specified and there is a fallback url in the intent extras, we open that url. If neither is * present, we alert the user that we were unable to open the link. * * @param msg A message with the uri with no handlers as the value for the "uri" key * @param callback A callback that will be called with success & no params if Java loads a page, * or with error and the uri to load if Java does not load a page */ private void openNoHandler(final NativeJSObject msg, final EventCallback callback) { final String uri = msg.getString("uri"); if (TextUtils.isEmpty(uri)) { Log.w(LOGTAG, "Received empty URL - loading about:neterror"); callback.sendError(getUnknownProtocolErrorPageUri("")); return; } final Intent intent; try { // TODO (bug 1173626): This will not handle android-app uris on non 5.1 devices. intent = Intent.parseUri(uri, 0); } catch (final URISyntaxException e) { String errorUri; try { errorUri = getUnknownProtocolErrorPageUri(URLEncoder.encode(uri, "UTF-8")); } catch (final UnsupportedEncodingException encodingE) { errorUri = getUnknownProtocolErrorPageUri(""); } // Don't log the exception to prevent leaking URIs. Log.w(LOGTAG, "Unable to parse Intent URI - loading about:neterror"); callback.sendError(errorUri); return; } // For this flow, we follow Chrome's lead: // https://developer.chrome.com/multidevice/android/intents if (intent.hasExtra(EXTRA_BROWSER_FALLBACK_URL)) { final String fallbackUrl = intent.getStringExtra(EXTRA_BROWSER_FALLBACK_URL); String urlToLoad; try { final String anyCaseScheme = new URI(fallbackUrl).getScheme(); final String scheme = (anyCaseScheme == null) ? null : anyCaseScheme.toLowerCase(Locale.US); if ("http".equals(scheme) || "https".equals(scheme)) { urlToLoad = fallbackUrl; } else { Log.w(LOGTAG, "Fallback URI uses unsupported scheme: " + scheme); urlToLoad = GENERIC_URI_PREFIX + fallbackUrl; } } catch (final URISyntaxException e) { // Do not include Exception to avoid leaking uris. Log.w(LOGTAG, "Exception parsing fallback URI"); urlToLoad = MALFORMED_URI_PREFIX + fallbackUrl; } callback.sendError(urlToLoad); } else if (intent.getPackage() != null) { // Note on alternative flows: we could get the intent package from a component, however, for // security reasons, components are ignored when opening URIs (bug 1168998) so we should // ignore it here too. // // Our old flow used to prompt the user to search for their app in the market by scheme and // while this could help the user find a new app, there is not always a correlation in // scheme to application name and we could end up steering the user wrong (potentially to // malicious software). Better to leave that one alone. final String marketUri = MARKET_INTENT_URI_PACKAGE_PREFIX + intent.getPackage(); final Intent marketIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(marketUri)); marketIntent.addCategory(Intent.CATEGORY_BROWSABLE); marketIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // (Bug 1192436) We don't know if marketIntent matches any Activities (e.g. non-Play // Store devices). If it doesn't, clicking the link will cause no action to occur. activity.startActivity(marketIntent); callback.sendSuccess(null); } else { // Don't log the URI to prevent leaking it. Log.w(LOGTAG, "Unable to open URI, default case - loading about:neterror"); callback.sendError(getUnknownProtocolErrorPageUri(intent.getData().toString())); } }