public void backStackPop() {
    // shouldn't be called when back stack is empty
    // catch wrong usage
    if (mBackStack.isEmpty()) {
      mBackStack.push(Pane.MAP);
    }

    final Pane pane = mBackStack.pop();
    switchToPane(pane);
  }
  @Override
  public boolean onOptionsItemSelected(final MenuItem item) {
    if (mNavigationHelper.onOptionsItemSelected(item)) return true;

    // Handle item selection
    final int itemId = item.getItemId();

    switch (itemId) {
      case android.R.id.home:
        switchToPane(Pane.MAP);
        return true;
      case R.id.reload_button:
        reloadIITC();
        return true;
      case R.id.toggle_fullscreen:
        mIitcWebView.toggleFullscreen();
        return true;
      case R.id.layer_chooser:
        mNavigationHelper.openRightDrawer();
        return true;
      case R.id.locate: // get the users current location and focus it on map
        switchToPane(Pane.MAP);

        if (mUserLocation.hasCurrentLocation()) {
          // if gps location is displayed we can use a better location without any costs
          mUserLocation.locate(mPersistentZoom);
        } else {
          // get location from network by default
          mIitcWebView.loadUrl(
              "javascript: window.map.locate({setView : true"
                  + (mPersistentZoom ? ", maxZoom : map.getZoom()" : "")
                  + "});");
        }
        return true;
      case R.id.action_settings: // start settings activity
        final Intent intent = new Intent(this, PreferenceActivity.class);
        try {
          intent.putExtra("iitc_version", mFileManager.getIITCVersion());
        } catch (final IOException e) {
          Log.w(e);
          return true;
        }
        startActivity(intent);
        return true;
      case R.id.menu_clear_cookies:
        final CookieManager cm = CookieManager.getInstance();
        cm.removeAllCookie();
        return true;
      case R.id.menu_send_screenshot:
        sendScreenshot();
        return true;
      case R.id.menu_debug:
        mDebugging = !mDebugging;
        updateViews();
        invalidateOptionsMenu();

        // TODO remove debugging stuff from JS?
        return true;
      default:
        return false;
    }
  }
  private void handleGeoUri(final Uri uri) throws URISyntaxException {
    final String[] parts = uri.getSchemeSpecificPart().split("\\?", 2);
    Double lat = null, lon = null;
    Integer z = null;
    String search = null;

    // parts[0] may contain an 'uncertainty' parameter, delimited by a semicolon
    final String[] pos = parts[0].split(";", 2)[0].split(",", 2);
    if (pos.length == 2) {
      try {
        lat = Double.valueOf(pos[0]);
        lon = Double.valueOf(pos[1]);
      } catch (final NumberFormatException e) {
        lat = null;
        lon = null;
      }
    }

    if (parts.length > 1) { // query string present
      // search for z=
      for (final String param : parts[1].split("&")) {
        if (param.startsWith("z=")) {
          try {
            z = Integer.valueOf(param.substring(2));
          } catch (final NumberFormatException e) {
          }
        }
        if (param.startsWith("q=")) {
          search = param.substring(2);
          final Pattern pattern =
              Pattern.compile("^(-?\\d+(\\.\\d+)?),(-?\\d+(\\.\\d+)?)\\s*\\(.+\\)");
          final Matcher matcher = pattern.matcher(search);
          if (matcher.matches()) {
            try {
              lat = Double.valueOf(matcher.group(1));
              lon = Double.valueOf(matcher.group(3));
              search = null; // if we have a position, we don't need the search term
            } catch (final NumberFormatException e) {
              lat = null;
              lon = null;
            }
          }
        }
      }
    }

    if (lat != null && lon != null) {
      String url = mIntelUrl + "?ll=" + lat + "," + lon;
      if (z != null) {
        url += "&z=" + z;
      }
      loadUrl(url);
      return;
    }

    if (search != null) {
      if (mIsLoading) {
        mSearchTerm = search;
        loadUrl(mIntelUrl);
      } else {
        switchToPane(Pane.MAP);
        mIitcWebView.loadUrl("javascript:search('" + search + "');");
      }
      return;
    }

    throw new URISyntaxException(uri.toString(), "position could not be parsed");
  }
  // handles ingress intel url intents, search intents, geo intents and javascript file intents
  private void handleIntent(final Intent intent, final boolean onCreate) {
    final String action = intent.getAction();
    if (Intent.ACTION_VIEW.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
      final Uri uri = intent.getData();
      Log.d("intent received url: " + uri.toString());

      if (uri.getScheme().equals("http") || uri.getScheme().equals("https")) {
        if (uri.getHost() != null
            && (uri.getHost().equals("ingress.com") || uri.getHost().endsWith(".ingress.com"))) {
          Log.d("loading url...");
          loadUrl(uri.toString());
          return;
        }
      }

      if (uri.getScheme().equals("geo")) {
        try {
          handleGeoUri(uri);
          return;
        } catch (final URISyntaxException e) {
          Log.w(e);
          new AlertDialog.Builder(this)
              .setTitle(R.string.intent_error)
              .setMessage(e.getReason())
              .setNeutralButton(
                  android.R.string.ok,
                  new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(final DialogInterface dialog, final int which) {
                      dialog.dismiss();
                    }
                  })
              .create()
              .show();
        }
      }

      // intent MIME type and uri path may be null
      final String type = intent.getType() == null ? "" : intent.getType();
      final String path = uri.getPath() == null ? "" : uri.getPath();
      if (path.endsWith(".user.js") || type.contains("javascript")) {
        final Intent prefIntent = new Intent(this, PluginPreferenceActivity.class);
        prefIntent.setDataAndType(uri, intent.getType());
        startActivity(prefIntent);
      }
    }

    if (Intent.ACTION_SEARCH.equals(action)) {
      String query = intent.getStringExtra(SearchManager.QUERY);
      query = query.replace("'", "''");
      final SearchView searchView = (SearchView) mSearchMenuItem.getActionView();
      searchView.setQuery(query, false);
      searchView.clearFocus();

      switchToPane(Pane.MAP);
      mIitcWebView.loadUrl("javascript:search('" + query + "');");
      return;
    }

    if (onCreate) {
      loadUrl(mIntelUrl);
    }
  }