Example #1
0
  private State loadDefaultConfig() {
    final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>();

    panelConfigs.add(
        createBuiltinPanelConfig(
            mContext, PanelType.TOP_SITES, EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));

    panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.BOOKMARKS));

    // We disable reader mode support on low memory devices. Hence the
    // reading list panel should not show up on such devices.
    if (!HardwareUtils.isLowMemoryPlatform()) {
      panelConfigs.add(createBuiltinPanelConfig(mContext, PanelType.READING_LIST));
    }

    final PanelConfig historyEntry = createBuiltinPanelConfig(mContext, PanelType.HISTORY);
    final PanelConfig recentTabsEntry = createBuiltinPanelConfig(mContext, PanelType.RECENT_TABS);

    // On tablets, the history panel is the last.
    // On phones, the history panel is the first one.
    if (HardwareUtils.isTablet()) {
      panelConfigs.add(historyEntry);
      panelConfigs.add(recentTabsEntry);
    } else {
      panelConfigs.add(0, historyEntry);
      panelConfigs.add(0, recentTabsEntry);
    }

    return new State(panelConfigs, true);
  }
 View getDoorHangerAnchor() {
   if (!HardwareUtils.isTablet()) {
     return mFavicon;
   } else {
     return mSiteSecurity;
   }
 }
  private void setSiteSecurityVisibility(boolean visible, EnumSet<UpdateFlags> flags) {
    // We don't hide site security on tablet.
    if (visible == mSiteSecurityVisible || HardwareUtils.isTablet()) {
      return;
    }

    mSiteSecurityVisible = visible;

    mTitle.clearAnimation();
    mSiteSecurity.clearAnimation();

    if (flags.contains(UpdateFlags.DISABLE_ANIMATIONS)) {
      mSiteSecurity.setVisibility(visible ? View.VISIBLE : View.GONE);
      return;
    }

    // If any of these animations were cancelled as a result of the
    // clearAnimation() calls above, we need to reset them.
    mLockFadeIn.reset();
    mTitleSlideLeft.reset();
    mTitleSlideRight.reset();

    if (mForwardAnim != null) {
      long delay = mForwardAnim.getRemainingTime();
      mTitleSlideRight.setStartOffset(delay);
      mTitleSlideLeft.setStartOffset(delay);
    } else {
      mTitleSlideRight.setStartOffset(0);
      mTitleSlideLeft.setStartOffset(0);
    }

    mTitle.startAnimation(visible ? mTitleSlideRight : mTitleSlideLeft);
  }
  private void updateFavicon(Tab tab) {
    if (HardwareUtils.isTablet()) {
      // We don't display favicons in the toolbar on tablet.
      return;
    }

    if (tab == null) {
      mFavicon.setImageDrawable(null);
      return;
    }

    Bitmap image = tab.getFavicon();

    if (image != null && image == mLastFavicon) {
      Log.d(LOGTAG, "Ignoring favicon: new image is identical to previous one.");
      return;
    }

    // Cache the original so we can debounce without scaling
    mLastFavicon = image;

    Log.d(LOGTAG, "updateFavicon(" + image + ")");

    if (image != null) {
      image = Bitmap.createScaledBitmap(image, mFaviconSize, mFaviconSize, false);
      mFavicon.setImageBitmap(image);
    } else {
      mFavicon.setImageResource(R.drawable.favicon);
    }
  }
 @Override
 public void onCreate() {
   HardwareUtils.init(getApplicationContext());
   Clipboard.init(getApplicationContext());
   GeckoLoader.loadMozGlue(getApplicationContext());
   super.onCreate();
 }
  /**
   * Create and insert a built-in panel configuration.
   *
   * @param context Android context.
   * @param jsonPanels array of JSON panels to update in place.
   * @param panelType to add.
   * @param positionOnPhones where to place the new panel on phones.
   * @param positionOnTablets where to place the new panel on tablets.
   * @throws JSONException
   */
  protected static void addBuiltinPanelConfig(
      Context context,
      JSONArray jsonPanels,
      PanelType panelType,
      Position positionOnPhones,
      Position positionOnTablets)
      throws JSONException {
    // Add the new panel.
    final JSONObject jsonPanelConfig = createBuiltinPanelConfig(context, panelType).toJSON();

    // If any panel is enabled, then we should make the new panel enabled.
    jsonPanelConfig.put(PanelConfig.JSON_KEY_DISABLED, allPanelsAreDisabled(jsonPanels));

    final boolean isTablet = HardwareUtils.isTablet();
    final boolean isPhone = !isTablet;

    // Maybe add the new panel to the front of the array.
    if ((isPhone && positionOnPhones == Position.FRONT)
        || (isTablet && positionOnTablets == Position.FRONT)) {
      // This is an inefficient way to stretch [a, b, c] to [a, a, b, c].
      for (int i = jsonPanels.length(); i >= 1; i--) {
        jsonPanels.put(i, jsonPanels.get(i - 1));
      }
      // And this inserts [d, a, b, c].
      jsonPanels.put(0, jsonPanelConfig);
    }

    // Maybe add the new panel to the back of the array.
    if ((isPhone && positionOnPhones == Position.BACK)
        || (isTablet && positionOnTablets == Position.BACK)) {
      jsonPanels.put(jsonPanelConfig);
    }
  }
  protected void init() {
    // Hide the default window background. Passing null prevents the below setOutTouchable()
    // call from working, so use an empty BitmapDrawable instead.
    setBackgroundDrawable(new BitmapDrawable(mContext.getResources()));

    // Allow the popup to be dismissed when touching outside.
    setOutsideTouchable(true);

    final int widthSpec =
        HardwareUtils.isTablet()
            ? ViewGroup.LayoutParams.WRAP_CONTENT
            : ViewGroup.LayoutParams.MATCH_PARENT;
    setWindowLayoutMode(widthSpec, ViewGroup.LayoutParams.WRAP_CONTENT);

    final LayoutInflater inflater = LayoutInflater.from(mContext);
    final ArrowPopupLayout layout = (ArrowPopupLayout) inflater.inflate(R.layout.arrow_popup, null);
    setContentView(layout);

    layout.mListener =
        new ArrowPopupLayout.OnSizeChangedListener() {
          @Override
          public void onSizeChanged() {
            if (mAnchor == null) {
              return;
            }

            // Remove padding from the width of the anchor when calculating the arrow offset.
            final int anchorWidth =
                mAnchor.getWidth() - mAnchor.getPaddingLeft() - mAnchor.getPaddingRight();

            // This is the difference between the edge of the anchor view and the edge of the arrow
            // view.
            // We're making an assumption here that the anchor view is wider than the arrow view.
            final int arrowOffset = (anchorWidth - mArrowWidth) / 2 + mAnchor.getPaddingLeft();

            // Calculate the distance between the left edge of the PopupWindow and the anchor.
            final int[] location = new int[2];
            mAnchor.getLocationOnScreen(location);
            final int anchorX = location[0];
            layout.getLocationOnScreen(location);
            final int popupX = location[0];
            final int leftMargin = anchorX - popupX + arrowOffset;

            // Offset the arrow by that amount to make the arrow align with the anchor. The
            // arrow is already offset by the PopupWindow position, so the total arrow offset
            // will be the compounded offset of the PopupWindow itself and the arrow's offset
            // within that window.
            final RelativeLayout.LayoutParams arrowLayoutParams =
                (RelativeLayout.LayoutParams) mArrow.getLayoutParams();
            arrowLayoutParams.setMargins(leftMargin, 0, 0, 0);
          }
        };

    mArrow = (ImageView) layout.findViewById(R.id.arrow);
    mContent = (LinearLayout) layout.findViewById(R.id.content);

    mInflated = true;
  }
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // We need to do this before we can query the hardware menu button state.
    // We're guaranteed to have an activity at this point (onAttach is called
    // before onCreate). It's okay to call this multiple times (with different
    // contexts).
    HardwareUtils.init(getActivity());

    addPreferences();
  }
Example #9
0
  private void openAppMenu() {
    assertMenuIsNotOpen();

    // This is a hack needed for tablets where the OverflowMenuButton is always in the GONE state,
    // so we press the menu key instead.
    if (HardwareUtils.hasMenuButton() || DeviceHelper.isTablet()) {
      mSolo.sendKey(Solo.MENU);
    } else {
      pressOverflowMenuButton();
    }

    waitForMenuOpen();
  }
  public ToolbarDisplayLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    setOrientation(HORIZONTAL);

    mActivity = (BrowserApp) context;

    LayoutInflater.from(context).inflate(R.layout.toolbar_display_layout, this);

    mTitle = (ThemedTextView) findViewById(R.id.url_bar_title);
    mTitlePadding = mTitle.getPaddingRight();

    final Resources res = getResources();

    mUrlColor = new ForegroundColorSpan(ColorUtils.getColor(context, R.color.url_bar_urltext));
    mBlockedColor =
        new ForegroundColorSpan(ColorUtils.getColor(context, R.color.url_bar_blockedtext));
    mDomainColor =
        new ForegroundColorSpan(ColorUtils.getColor(context, R.color.url_bar_domaintext));
    mPrivateDomainColor =
        new ForegroundColorSpan(ColorUtils.getColor(context, R.color.url_bar_domaintext_private));

    mFavicon = (ImageButton) findViewById(R.id.favicon);
    mSiteSecurity = (ImageButton) findViewById(R.id.site_security);

    if (HardwareUtils.isTablet()) {
      mSiteSecurity.setVisibility(View.VISIBLE);

      // We don't show favicons in the toolbar on new tablet. Note that while we could
      // null the favicon reference, we don't do so to avoid excessive null-checking.
      removeView(mFavicon);
    } else {
      if (Versions.feature16Plus) {
        mFavicon.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
      }
      mFaviconSize = Math.round(Favicons.browserToolbarFaviconSize);
    }

    mSiteSecurityVisible = (mSiteSecurity.getVisibility() == View.VISIBLE);

    mSiteIdentityPopup = new SiteIdentityPopup(mActivity);
    mSiteIdentityPopup.setAnchor(this);
    mSiteIdentityPopup.setOnVisibilityChangeListener(mActivity);

    mStop = (ImageButton) findViewById(R.id.stop);
    mPageActionLayout = (PageActionLayout) findViewById(R.id.page_action_layout);
  }
Example #11
0
 @Override
 public String getDefaultUAString() {
   return HardwareUtils.isTablet()
       ? AppConstants.USER_AGENT_FENNEC_TABLET
       : AppConstants.USER_AGENT_FENNEC_MOBILE;
 }
  /**
   * Check for conditions for building certain settings, and add them to be tested if they are
   * present.
   */
  public void updateConditionalSettings(Map<String[], List<String[]>> settingsMap) {
    // Preferences dependent on RELEASE_BUILD
    if (!AppConstants.RELEASE_BUILD) {
      // Text reflow - only built if *not* release build
      String[] textReflowUi = {mStringHelper.TEXT_REFLOW_LABEL};
      settingsMap.get(PATH_DISPLAY).add(textReflowUi);

      if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED) {
        // Anonymous cell tower/wifi collection
        String[] networkReportingUi = {
          "Mozilla Location Service",
          "Help Mozilla map the world! Share the approximate Wi-Fi and cellular location of your device to improve our geolocation service."
        };
        settingsMap.get(PATH_MOZILLA).add(networkReportingUi);

        String[] learnMoreUi = {"Learn more"};
        settingsMap.get(PATH_MOZILLA).add(learnMoreUi);
      }
    }

    if (!AppConstants.NIGHTLY_BUILD) {
      final List<String[]> privacy = settingsMap.get(PATH_PRIVACY);
      privacy.remove(TRACKING_PROTECTION_LABEL_ARR);
      privacy.remove(MANAGE_LOGINS_ARR);
    }

    // Automatic updates
    if (AppConstants.MOZ_UPDATER) {
      String[] autoUpdateUi = {
        "Download updates automatically", "Only over Wi-Fi", "Always", "Only over Wi-Fi", "Never"
      };
      settingsMap.get(PATH_CUSTOMIZE).add(autoUpdateUi);
    }

    // Tab Queue
    if (AppConstants.NIGHTLY_BUILD && AppConstants.MOZ_ANDROID_TAB_QUEUE) {
      final String expected =
          "Queue links for later instead of switching to "
              + mStringHelper.BRAND_NAME
              + " each time";
      String[] tabQueue = {mStringHelper.TAB_QUEUE_LABEL, expected};
      settingsMap.get(PATH_CUSTOMIZE).add(tabQueue);
    }

    // Crash reporter
    if (AppConstants.MOZ_CRASHREPORTER) {
      String[] crashReporterUi = {
        "Crash Reporter",
        mStringHelper.BRAND_NAME
            + " submits crash reports to help Mozilla make your browser more stable and secure"
      };
      settingsMap.get(PATH_MOZILLA).add(crashReporterUi);
    }

    // Telemetry
    if (AppConstants.MOZ_TELEMETRY_REPORTING) {
      String[] telemetryUi = {
        "Telemetry",
        "Shares performance, usage, hardware and customization data about your browser with Mozilla to help us make "
            + mStringHelper.BRAND_NAME
            + " better"
      };
      settingsMap.get(PATH_MOZILLA).add(telemetryUi);
    }

    // Tablet: we don't allow a page title option.
    if (HardwareUtils.isTablet()) {
      settingsMap.get(PATH_DISPLAY).remove(TITLE_BAR_LABEL_ARR);
    }
  }
  protected void addPreferences() {
    addPreferencesFromResource(R.xml.fxaccount_status_prefscreen);

    accountCategory = (PreferenceCategory) ensureFindPreference("signed_in_as_category");
    profilePreference = ensureFindPreference("profile");
    emailPreference = ensureFindPreference("email");
    if (AppConstants.MOZ_ANDROID_FIREFOX_ACCOUNT_PROFILES) {
      accountCategory.removePreference(emailPreference);
    } else {
      accountCategory.removePreference(profilePreference);
    }
    authServerPreference = ensureFindPreference("auth_server");

    needsPasswordPreference = ensureFindPreference("needs_credentials");
    needsUpgradePreference = ensureFindPreference("needs_upgrade");
    needsVerificationPreference = ensureFindPreference("needs_verification");
    needsMasterSyncAutomaticallyEnabledPreference =
        ensureFindPreference("needs_master_sync_automatically_enabled");
    needsFinishMigratingPreference = ensureFindPreference("needs_finish_migrating");

    syncCategory = (PreferenceCategory) ensureFindPreference("sync_category");

    bookmarksPreference = (CheckBoxPreference) ensureFindPreference("bookmarks");
    historyPreference = (CheckBoxPreference) ensureFindPreference("history");
    tabsPreference = (CheckBoxPreference) ensureFindPreference("tabs");
    passwordsPreference = (CheckBoxPreference) ensureFindPreference("passwords");

    if (!FxAccountUtils.LOG_PERSONAL_INFORMATION) {
      removeDebugButtons();
    } else {
      connectDebugButtons();
      ALWAYS_SHOW_AUTH_SERVER = true;
      ALWAYS_SHOW_SYNC_SERVER = true;
    }

    if (AppConstants.MOZ_ANDROID_FIREFOX_ACCOUNT_PROFILES) {
      profilePreference.setOnPreferenceClickListener(this);
    } else {
      emailPreference.setOnPreferenceClickListener(this);
    }

    needsPasswordPreference.setOnPreferenceClickListener(this);
    needsVerificationPreference.setOnPreferenceClickListener(this);
    needsFinishMigratingPreference.setOnPreferenceClickListener(this);

    bookmarksPreference.setOnPreferenceClickListener(this);
    historyPreference.setOnPreferenceClickListener(this);
    tabsPreference.setOnPreferenceClickListener(this);
    passwordsPreference.setOnPreferenceClickListener(this);

    deviceNamePreference = (EditTextPreference) ensureFindPreference("device_name");
    deviceNamePreference.setOnPreferenceChangeListener(this);

    syncServerPreference = ensureFindPreference("sync_server");
    morePreference = ensureFindPreference("more");
    morePreference.setOnPreferenceClickListener(this);

    syncNowPreference = ensureFindPreference("sync_now");
    syncNowPreference.setEnabled(true);
    syncNowPreference.setOnPreferenceClickListener(this);

    if (HardwareUtils.hasMenuButton()) {
      syncCategory.removePreference(morePreference);
    }
  }
Example #14
0
  /**
   * Migrates JSON config data storage.
   *
   * @param context Context used to get shared preferences and create built-in panel.
   * @param jsonString String currently stored in preferences.
   * @return JSONArray array representing new set of panel configs.
   */
  private static synchronized JSONArray maybePerformMigration(Context context, String jsonString)
      throws JSONException {
    // If the migration is already done, we're at the current version.
    if (sMigrationDone) {
      final JSONObject json = new JSONObject(jsonString);
      return json.getJSONArray(JSON_KEY_PANELS);
    }

    // Make sure we only do this version check once.
    sMigrationDone = true;

    final JSONArray originalJsonPanels;
    final int version;

    final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
    if (prefs.contains(PREFS_CONFIG_KEY_OLD)) {
      // Our original implementation did not contain versioning, so this is implicitly version 0.
      originalJsonPanels = new JSONArray(jsonString);
      version = 0;
    } else {
      final JSONObject json = new JSONObject(jsonString);
      originalJsonPanels = json.getJSONArray(JSON_KEY_PANELS);
      version = json.getInt(JSON_KEY_VERSION);
    }

    if (version == VERSION) {
      return originalJsonPanels;
    }

    Log.d(LOGTAG, "Performing migration");

    final JSONArray newJsonPanels = new JSONArray();
    final SharedPreferences.Editor prefsEditor = prefs.edit();

    for (int v = version + 1; v <= VERSION; v++) {
      Log.d(LOGTAG, "Migrating to version = " + v);

      switch (v) {
        case 1:
          // Add "Recent Tabs" panel
          final PanelConfig recentTabsConfig =
              createBuiltinPanelConfig(context, PanelType.RECENT_TABS);
          final JSONObject jsonRecentTabsConfig = recentTabsConfig.toJSON();

          // Add the new panel to the front of the array on phones.
          if (!HardwareUtils.isTablet()) {
            newJsonPanels.put(jsonRecentTabsConfig);
          }

          // Copy the original panel configs.
          final int count = originalJsonPanels.length();
          for (int i = 0; i < count; i++) {
            final JSONObject jsonPanelConfig = originalJsonPanels.getJSONObject(i);
            newJsonPanels.put(jsonPanelConfig);
          }

          // Add the new panel to the end of the array on tablets.
          if (HardwareUtils.isTablet()) {
            newJsonPanels.put(jsonRecentTabsConfig);
          }

          // Remove the old pref key.
          prefsEditor.remove(PREFS_CONFIG_KEY_OLD);
          break;
      }
    }

    // Save the new panel config and the new version number.
    final JSONObject newJson = new JSONObject();
    newJson.put(JSON_KEY_PANELS, newJsonPanels);
    newJson.put(JSON_KEY_VERSION, VERSION);

    prefsEditor.putString(PREFS_CONFIG_KEY, newJson.toString());
    prefsEditor.commit();

    return newJsonPanels;
  }
Example #15
0
  public void show(Panel panelToShow) {
    if (!isShown()) setVisibility(View.VISIBLE);

    if (mPanel != null) {
      // Hide the old panel.
      mPanel.hide();
    }

    final boolean showAnimation = !mVisible;
    mVisible = true;
    mCurrentPanel = panelToShow;

    int index = panelToShow.ordinal();
    mTabWidget.setCurrentTab(index);

    switch (panelToShow) {
      case NORMAL_TABS:
        mPanel = mPanelNormal;
        break;
      case PRIVATE_TABS:
        mPanel = mPanelPrivate;
        break;
      case REMOTE_TABS:
        mPanel = mPanelRemote;
        break;

      default:
        throw new IllegalArgumentException("Unknown panel type " + panelToShow);
    }
    mPanel.show();

    if (mCurrentPanel == Panel.REMOTE_TABS) {
      if (mFooter != null) mFooter.setVisibility(View.GONE);

      mAddTab.setVisibility(View.INVISIBLE);

      mMenuButton.setVisibility(View.GONE);
    } else {
      if (mFooter != null) mFooter.setVisibility(View.VISIBLE);

      mAddTab.setVisibility(View.VISIBLE);
      mAddTab.setImageLevel(index);

      if (!HardwareUtils.hasMenuButton()) {
        mMenuButton.setVisibility(View.VISIBLE);
        mMenuButton.setEnabled(true);
        mPopupMenu.setAnchor(mMenuButton);
      } else {
        mPopupMenu.setAnchor(mAddTab);
      }
    }

    if (isSideBar()) {
      if (showAnimation) dispatchLayoutChange(getWidth(), getHeight());
    } else {
      int actionBarHeight =
          mContext.getResources().getDimensionPixelSize(R.dimen.browser_toolbar_height);
      int height = actionBarHeight + getTabContainerHeight(mTabsContainer);
      dispatchLayoutChange(getWidth(), height);
    }
    mHeaderVisible = true;
  }
Example #16
0
  /**
   * If applicable, download and select the distribution specified in the referrer intent.
   *
   * @return true if a referrer-supplied distribution was selected.
   */
  private boolean checkIntentDistribution(final ReferrerDescriptor referrer) {
    if (referrer == null) {
      return false;
    }

    URI uri = getReferredDistribution(referrer);
    if (uri == null) {
      return false;
    }

    long start = SystemClock.uptimeMillis();
    Log.v(LOGTAG, "Downloading referred distribution: " + uri);

    try {
      final HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();

      // If the Search Activity starts, and we handle the referrer intent, this'll return
      // null. Recover gracefully in this case.
      final GeckoAppShell.GeckoInterface geckoInterface = GeckoAppShell.getGeckoInterface();
      final String ua;
      if (geckoInterface == null) {
        // Fall back to GeckoApp's default implementation.
        ua =
            HardwareUtils.isTablet()
                ? AppConstants.USER_AGENT_FENNEC_TABLET
                : AppConstants.USER_AGENT_FENNEC_MOBILE;
      } else {
        ua = geckoInterface.getDefaultUAString();
      }

      connection.setRequestProperty(HTTP.USER_AGENT, ua);
      connection.setRequestProperty("Accept", EXPECTED_CONTENT_TYPE);

      try {
        final JarInputStream distro;
        try {
          distro = fetchDistribution(uri, connection);
        } catch (Exception e) {
          Log.e(LOGTAG, "Error fetching distribution from network.", e);
          recordFetchTelemetry(e);
          return false;
        }

        long end = SystemClock.uptimeMillis();
        final long duration = end - start;
        Log.d(LOGTAG, "Distro fetch took " + duration + "ms; result? " + (distro != null));
        Telemetry.addToHistogram(
            HISTOGRAM_DOWNLOAD_TIME_MS, clamp(MAX_DOWNLOAD_TIME_MSEC, duration));

        if (distro == null) {
          // Nothing to do.
          return false;
        }

        // Try to copy distribution files from the fetched stream.
        try {
          Log.d(LOGTAG, "Copying files from fetched zip.");
          if (copyFilesFromStream(distro)) {
            // We always copy to the data dir, and we only copy files from
            // a 'distribution' subdirectory. Now determine our actual distribution directory.
            return checkDataDistribution();
          }
        } catch (SecurityException e) {
          Log.e(LOGTAG, "Security exception copying files. Corrupt or malicious?", e);
          Telemetry.addToHistogram(
              HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_POST_FETCH_SECURITY_EXCEPTION);
        } catch (Exception e) {
          Log.e(LOGTAG, "Error copying files from distribution.", e);
          Telemetry.addToHistogram(HISTOGRAM_CODE_CATEGORY, CODE_CATEGORY_POST_FETCH_EXCEPTION);
        } finally {
          distro.close();
        }
      } finally {
        connection.disconnect();
      }
    } catch (IOException e) {
      Log.e(LOGTAG, "Error copying distribution files from network.", e);
      recordFetchTelemetry(e);
    }

    return false;
  }
  /**
   * Check for conditions for building certain settings, and add them to be tested if they are
   * present.
   */
  public void updateConditionalSettings(Map<String[], List<String[]>> settingsMap) {
    // Preferences dependent on RELEASE_BUILD
    if (!AppConstants.RELEASE_BUILD) {
      // Text reflow - only built if *not* release build
      String[] textReflowUi = {mStringHelper.TEXT_REFLOW_LABEL};
      settingsMap.get(PATH_DISPLAY).add(textReflowUi);

      if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED) {
        // Anonymous cell tower/wifi collection
        String[] networkReportingUi = {
          "Mozilla Location Service",
          "Help Mozilla map the world! Share the approximate Wi-Fi and cellular location of your device to improve our geolocation service."
        };
        settingsMap.get(PATH_MOZILLA).add(networkReportingUi);

        String[] learnMoreUi = {"Learn more"};
        settingsMap.get(PATH_MOZILLA).add(learnMoreUi);
      }
    }

    if (!AppConstants.NIGHTLY_BUILD) {
      final List<String[]> privacy = settingsMap.get(PATH_PRIVACY);
      privacy.remove(MANAGE_LOGINS_ARR);
    }

    // Automatic updates
    if (AppConstants.MOZ_UPDATER) {
      String[] autoUpdateUi = {
        "Download updates automatically", "Only over Wi-Fi", "Always", "Only over Wi-Fi", "Never"
      };
      settingsMap.get(PATH_CUSTOMIZE).add(autoUpdateUi);
    }

    // Tab Queue
    if (AppConstants.NIGHTLY_BUILD && AppConstants.MOZ_ANDROID_TAB_QUEUE) {
      final String[] tabQueue = {mStringHelper.TAB_QUEUE_LABEL, mStringHelper.TAB_QUEUE_SUMMARY};
      settingsMap.get(PATH_CUSTOMIZE).add(tabQueue);
    }

    // Crash reporter
    if (AppConstants.MOZ_CRASHREPORTER) {
      String[] crashReporterUi = {
        "Crash Reporter",
        mStringHelper.BRAND_NAME
            + " submits crash reports to help Mozilla make your browser more stable and secure"
      };
      settingsMap.get(PATH_MOZILLA).add(crashReporterUi);
    }

    // Telemetry
    if (AppConstants.MOZ_TELEMETRY_REPORTING) {
      String[] telemetryUi = {
        "Telemetry",
        "Shares performance, usage, hardware and customization data about your browser with Mozilla to help us make "
            + mStringHelper.BRAND_NAME
            + " better"
      };
      settingsMap.get(PATH_MOZILLA).add(telemetryUi);
    }

    // Tablet: we don't allow a page title option.
    if (HardwareUtils.isTablet()) {
      settingsMap.get(PATH_DISPLAY).remove(TITLE_BAR_LABEL_ARR);
    }

    // Voice input
    if (InputOptionsUtils.supportsVoiceRecognizer(
        this.getActivity().getApplicationContext(),
        this.getActivity().getResources().getString(R.string.voicesearch_prompt))) {
      String[] voiceInputUi = {
        mStringHelper.VOICE_INPUT_TITLE_LABEL, mStringHelper.VOICE_INPUT_SUMMARY_LABEL
      };
      settingsMap.get(PATH_DISPLAY).add(voiceInputUi);
    }

    // QR Code input
    if (InputOptionsUtils.supportsQrCodeReader(this.getActivity().getApplicationContext())) {
      String[] qrCodeInputUi = {
        mStringHelper.QRCODE_INPUT_TITLE_LABEL, mStringHelper.QRCODE_INPUT_SUMMARY_LABEL
      };
      settingsMap.get(PATH_DISPLAY).add(qrCodeInputUi);
    }
  }
Example #18
0
  private void init(Context context, String url, boolean doInit) {
    // TODO: Fennec currently takes care of its own initialization, so this
    // flag is a hack used in Fennec to prevent GeckoView initialization.
    // This should go away once Fennec also uses GeckoView for
    // initialization.
    if (!doInit) return;

    // If running outside of a GeckoActivity (eg, from a library project),
    // load the native code and disable content providers
    boolean isGeckoActivity = false;
    try {
      isGeckoActivity = context instanceof GeckoActivity;
    } catch (NoClassDefFoundError ex) {
    }

    if (!isGeckoActivity) {
      // Set the GeckoInterface if the context is an activity and the GeckoInterface
      // has not already been set
      if (context instanceof Activity && getGeckoInterface() == null) {
        setGeckoInterface(new BaseGeckoInterface(context));
      }

      Clipboard.init(context);
      HardwareUtils.init(context);

      // If you want to use GeckoNetworkManager, start it.

      GeckoLoader.loadMozGlue();
      BrowserDB.setEnableContentProviders(false);
    }

    if (url != null) {
      GeckoThread.setUri(url);
      GeckoThread.setAction(Intent.ACTION_VIEW);
      GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(url));
    }
    GeckoAppShell.setContextGetter(this);
    if (context instanceof Activity) {
      Tabs tabs = Tabs.getInstance();
      tabs.attachToContext(context);
    }

    EventDispatcher.getInstance()
        .registerGeckoThreadListener(
            this,
            "Gecko:Ready",
            "Content:StateChange",
            "Content:LoadError",
            "Content:PageShow",
            "DOMTitleChanged",
            "Link:Favicon",
            "Prompt:Show",
            "Prompt:ShowTop");

    ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
    initializeView(EventDispatcher.getInstance());

    if (GeckoThread.checkAndSetLaunchState(
        GeckoThread.LaunchState.Launching, GeckoThread.LaunchState.Launched)) {
      // This is the first launch, so finish initialization and go.
      GeckoProfile profile = GeckoProfile.get(context).forceCreate();
      BrowserDB.initialize(profile.getName());

      GeckoAppShell.setLayerView(this);
      GeckoThread.createAndStart();
    } else if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
      // If Gecko is already running, that means the Activity was
      // destroyed, so we need to re-attach Gecko to this GeckoView.
      connectToGecko();
    }
  }
  public void checkMenuHierarchy(Map<String[], List<String[]>> settingsMap) {
    // Check the items within each category.
    String section = null;
    for (Entry<String[], List<String[]>> e : settingsMap.entrySet()) {
      final String[] menuPath = e.getKey();

      for (String menuItem : menuPath) {
        section = "^" + menuItem + "$";

        waitForEnabledText(section);
        mSolo.clickOnText(section);
      }

      List<String[]> sectionItems = e.getValue();

      // Check each item of the section.
      for (String[] item : sectionItems) {
        int itemLen = item.length;

        // Each item must at least have a title.
        mAsserter.ok(item.length > 0, "Section-item", "Each item must at least have a title");

        // Check item title.
        String itemTitle = "^" + item[0] + "$";
        boolean foundText = waitForPreferencesText(itemTitle);

        mAsserter.ok(
            foundText,
            "Waiting for settings item " + itemTitle + " in section " + section,
            "The " + itemTitle + " option is present in section " + section);
        // Check item default, if it exists.
        if (itemLen > 1) {
          String itemDefault = "^" + item[1] + "$";
          foundText = waitForPreferencesText(itemDefault);
          mAsserter.ok(
              foundText,
              "Waiting for settings item default " + itemDefault + " in section " + section,
              "The " + itemDefault + " default is present in section " + section);
        }
        // Check item choices, if they exist.
        if (itemLen > 2) {
          waitForEnabledText(itemTitle);
          mSolo.clickOnText(itemTitle);
          for (int i = 2; i < itemLen; i++) {
            String itemChoice = "^" + item[i] + "$";
            foundText = waitForPreferencesText(itemChoice);
            mAsserter.ok(
                foundText,
                "Waiting for settings item choice " + itemChoice + " in section " + section,
                "The " + itemChoice + " choice is present in section " + section);
          }

          // Leave submenu after checking.
          if (waitForText("^Cancel$")) {
            mSolo.clickOnText("^Cancel$");
          } else {
            // Some submenus aren't dialogs, but are nested screens; exit using "back".
            mSolo.goBack();
          }
        }
      }

      // Navigate back if on a phone or small tablets. Large tablets
      // shouldn't do this because they use headers and fragments.
      if (mDevice.type.equals("phone") || HardwareUtils.isSmallTablet()) {
        int menuDepth = menuPath.length;
        while (menuDepth > 0) {
          mSolo.goBack();
          menuDepth--;
          // Sleep so subsequent back actions aren't lost.
          mSolo.sleep(150);
        }
      }
    }
  }