/** This is called when the native library are ready. */
  public void onNativeLibraryReady(
      WindowAndroid windowAndroid, TabContentManager tabContentManager) {
    assert mLayerTitleCache == null : "Should be called once";

    if (DeviceClassManager.enableLayerDecorationCache()) {
      mLayerTitleCache = new LayerTitleCache(getContext());
    }

    mCompositorView.initNativeCompositor(
        SysUtils.isLowEndDevice(), windowAndroid, mLayerTitleCache, tabContentManager);

    if (mLayerTitleCache != null) {
      mLayerTitleCache.setResourceManager(getResourceManager());
    }

    if (mControlContainer != null) {
      mCompositorView
          .getResourceManager()
          .getDynamicResourceLoader()
          .registerResource(R.id.control_container, mControlContainer.getToolbarResourceAdapter());

      ViewResourceAdapter progressAdapter = mControlContainer.getProgressResourceAdapter();
      if (progressAdapter != null) {
        mCompositorView
            .getResourceManager()
            .getDynamicResourceLoader()
            .registerResource(R.id.progress, progressAdapter);
      }
    }
  }
  private void startModerateBindingManagementIfNeeded() {
    // Moderate binding doesn't apply to low end devices.
    if (SysUtils.isLowEndDevice()) return;

    boolean moderateBindingTillBackgrounded =
        FieldTrialList.findFullName("ModerateBindingOnBackgroundTabCreation").equals("Enabled");
    ChildProcessLauncher.startModerateBindingManagement(
        mAppContext, moderateBindingTillBackgrounded);
  }
  /**
   * The {@link DeviceClassManager} constructor should be self contained and rely on system
   * information and command line flags.
   */
  private DeviceClassManager() {
    // Device based configurations.
    if (SysUtils.isLowEndDevice()) {
      mEnableSnapshots = false;
      mEnableLayerDecorationCache = true;
      mEnableAccessibilityLayout = true;
      mEnableAnimations = false;
      mEnablePrerendering = false;
      mEnableToolbarSwipe = false;
      mDisableDomainReliability = true;
    } else {
      mEnableSnapshots = true;
      mEnableLayerDecorationCache = true;
      mEnableAccessibilityLayout = false;
      mEnableAnimations = true;
      mEnablePrerendering = true;
      mEnableToolbarSwipe = true;
      mDisableDomainReliability = false;
    }

    if (DeviceFormFactor.isTablet(ApplicationStatus.getApplicationContext())) {
      mEnableAccessibilityLayout = false;
    }

    // Flag based configurations.
    CommandLine commandLine = CommandLine.getInstance();
    mEnableAccessibilityLayout |=
        commandLine.hasSwitch(ChromeSwitches.ENABLE_ACCESSIBILITY_TAB_SWITCHER);
    mEnableFullscreen = !commandLine.hasSwitch(ChromeSwitches.DISABLE_FULLSCREEN);
    mEnableUndo = commandLine.hasSwitch(ChromeSwitches.ENABLE_HIGH_END_UI_UNDO);
    mEnableToolbarSwipeInDocumentMode =
        commandLine.hasSwitch(ChromeSwitches.ENABLE_TOOLBAR_SWIPE_IN_DOCUMENT_MODE);

    // Related features.
    if (mEnableAccessibilityLayout) {
      mEnableAnimations = false;
    }

    if (SysUtils.isLowEndDevice() || mEnableAccessibilityLayout) {
      mEnableUndo = true;
    }
  }
Exemple #4
0
  // Used internally to initialize the linker's static data. Assume lock is held.
  private static void ensureInitializedLocked() {
    assert Thread.holdsLock(Linker.class);

    if (!sInitialized) {
      sRelroSharingSupported = false;
      if (NativeLibraries.USE_LINKER) {
        if (DEBUG) Log.i(TAG, "Loading lib" + TAG + ".so");
        try {
          System.loadLibrary(TAG);
        } catch (UnsatisfiedLinkError e) {
          // In a component build, the ".cr" suffix is added to each library name.
          System.loadLibrary(TAG + ".cr");
        }
        sRelroSharingSupported = nativeCanUseSharedRelro();
        if (!sRelroSharingSupported) Log.w(TAG, "This system cannot safely share RELRO sections");
        else {
          if (DEBUG) Log.i(TAG, "This system supports safe shared RELRO sections");
        }

        if (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_INIT) {
          sMemoryDeviceConfig =
              SysUtils.isLowEndDevice() ? MEMORY_DEVICE_CONFIG_LOW : MEMORY_DEVICE_CONFIG_NORMAL;
        }

        switch (BROWSER_SHARED_RELRO_CONFIG) {
          case BROWSER_SHARED_RELRO_CONFIG_NEVER:
            sBrowserUsesSharedRelro = false;
            break;
          case BROWSER_SHARED_RELRO_CONFIG_LOW_RAM_ONLY:
            sBrowserUsesSharedRelro = (sMemoryDeviceConfig == MEMORY_DEVICE_CONFIG_LOW);
            if (sBrowserUsesSharedRelro)
              Log.w(TAG, "Low-memory device: shared RELROs used in all processes");
            break;
          case BROWSER_SHARED_RELRO_CONFIG_ALWAYS:
            Log.w(TAG, "Beware: shared RELROs used in all processes!");
            sBrowserUsesSharedRelro = true;
            break;
          default:
            assert false : "Unreached";
            break;
        }
      } else {
        if (DEBUG) Log.i(TAG, "Linker disabled");
      }

      if (!sRelroSharingSupported) {
        // Sanity.
        sBrowserUsesSharedRelro = false;
        sWaitForSharedRelros = false;
      }

      sInitialized = true;
    }
  }
  /**
   * Creates and shows the app menu anchored to the specified view.
   *
   * @param context The context of the AppMenu (ensure the proper theme is set on this context).
   * @param anchorView The anchor {@link View} of the {@link ListPopupWindow}.
   * @param isByPermanentButton Whether or not permanent hardware button triggered it. (oppose to
   *     software button or keyboard).
   * @param screenRotation Current device screen rotation.
   * @param visibleDisplayFrame The display area rect in which AppMenu is supposed to fit in.
   * @param screenHeight Current device screen height.
   * @param footerResourceId The resource id for a view to add to the end of the menu list. Can be 0
   *     if no such view is required.
   */
  void show(
      Context context,
      View anchorView,
      boolean isByPermanentButton,
      int screenRotation,
      Rect visibleDisplayFrame,
      int screenHeight,
      int footerResourceId) {
    mPopup = new ListPopupWindow(context, null, android.R.attr.popupMenuStyle);
    mPopup.setModal(true);
    mPopup.setAnchorView(anchorView);
    mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);

    int footerHeight = 0;
    if (footerResourceId != 0) {
      mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
      View promptView = LayoutInflater.from(context).inflate(footerResourceId, null);
      mPopup.setPromptView(promptView);
      int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
      promptView.measure(measureSpec, measureSpec);
      footerHeight = promptView.getMeasuredHeight();
    }
    mPopup.setOnDismissListener(
        new OnDismissListener() {
          @Override
          public void onDismiss() {
            if (mPopup.getAnchorView() instanceof ImageButton) {
              ((ImageButton) mPopup.getAnchorView()).setSelected(false);
            }

            if (mMenuItemEnterAnimator != null) mMenuItemEnterAnimator.cancel();

            mHandler.appMenuDismissed();
            mHandler.onMenuVisibilityChanged(false);
          }
        });

    // Some OEMs don't actually let us change the background... but they still return the
    // padding of the new background, which breaks the menu height.  If we still have a
    // drawable here even though our style says @null we should use this padding instead...
    Drawable originalBgDrawable = mPopup.getBackground();

    // Need to explicitly set the background here.  Relying on it being set in the style caused
    // an incorrectly drawn background.
    if (isByPermanentButton) {
      mPopup.setBackgroundDrawable(
          ApiCompatibilityUtils.getDrawable(context.getResources(), R.drawable.menu_bg));
    } else {
      mPopup.setBackgroundDrawable(
          ApiCompatibilityUtils.getDrawable(context.getResources(), R.drawable.edge_menu_bg));
      mPopup.setAnimationStyle(R.style.OverflowMenuAnim);
    }

    // Turn off window animations for low end devices, and on Android M, which has built-in menu
    // animations.
    if (SysUtils.isLowEndDevice() || Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
      mPopup.setAnimationStyle(0);
    }

    Rect bgPadding = new Rect();
    mPopup.getBackground().getPadding(bgPadding);

    int popupWidth =
        context.getResources().getDimensionPixelSize(R.dimen.menu_width)
            + bgPadding.left
            + bgPadding.right;

    mPopup.setWidth(popupWidth);

    mCurrentScreenRotation = screenRotation;
    mIsByPermanentButton = isByPermanentButton;

    // Extract visible items from the Menu.
    int numItems = mMenu.size();
    List<MenuItem> menuItems = new ArrayList<MenuItem>();
    for (int i = 0; i < numItems; ++i) {
      MenuItem item = mMenu.getItem(i);
      if (item.isVisible()) {
        menuItems.add(item);
      }
    }

    Rect sizingPadding = new Rect(bgPadding);
    if (isByPermanentButton && originalBgDrawable != null) {
      Rect originalPadding = new Rect();
      originalBgDrawable.getPadding(originalPadding);
      sizingPadding.top = originalPadding.top;
      sizingPadding.bottom = originalPadding.bottom;
    }

    // A List adapter for visible items in the Menu. The first row is added as a header to the
    // list view.
    mAdapter = new AppMenuAdapter(this, menuItems, LayoutInflater.from(context));
    mPopup.setAdapter(mAdapter);

    setMenuHeight(menuItems.size(), visibleDisplayFrame, screenHeight, sizingPadding, footerHeight);
    setPopupOffset(mPopup, mCurrentScreenRotation, visibleDisplayFrame, sizingPadding);
    mPopup.setOnItemClickListener(this);
    mPopup.show();
    mPopup.getListView().setItemsCanFocus(true);
    mPopup.getListView().setOnKeyListener(this);

    mHandler.onMenuVisibilityChanged(true);

    if (mVerticalFadeDistance > 0) {
      mPopup.getListView().setVerticalFadingEdgeEnabled(true);
      mPopup.getListView().setFadingEdgeLength(mVerticalFadeDistance);
    }

    // Don't animate the menu items for low end devices.
    if (!SysUtils.isLowEndDevice() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
      mPopup
          .getListView()
          .addOnLayoutChangeListener(
              new View.OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(
                    View v,
                    int left,
                    int top,
                    int right,
                    int bottom,
                    int oldLeft,
                    int oldTop,
                    int oldRight,
                    int oldBottom) {
                  mPopup.getListView().removeOnLayoutChangeListener(this);
                  runMenuItemEnterAnimations();
                }
              });
    }
  }
  /**
   * Creates a new tab and posts to UI.
   *
   * @param loadUrlParams parameters of the url load.
   * @param type Information about how the tab was launched.
   * @param parent the parent tab, if present.
   * @param position the requested position (index in the tab model)
   * @param intent the source of the url if it isn't null.
   * @return The new tab.
   */
  public ChromeTab createNewTab(
      LoadUrlParams loadUrlParams,
      TabModel.TabLaunchType type,
      Tab parent,
      int position,
      Intent intent) {
    try {
      TraceEvent.begin("ChromeTabCreator.createNewTab");
      int parentId = parent != null ? parent.getId() : Tab.INVALID_TAB_ID;
      WebContents webContents = IntentHandler.getWebContentsFromIntent(intent);
      boolean isWebContentsPaused = false;
      if (webContents != null) {
        // The WebContents comes with additional data, but it shouldn't be used if the
        // WebContents itself couldn't be parsed out.
        parentId =
            IntentUtils.safeGetIntExtra(
                intent, IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID);
        isWebContentsPaused =
            IntentUtils.safeGetBooleanExtra(intent, IntentHandler.EXTRA_WEB_CONTENTS_PAUSED, false);
      }

      // Sanitize the url.
      loadUrlParams.setUrl(UrlUtilities.fixupUrl(loadUrlParams.getUrl()));
      loadUrlParams.setTransitionType(getTransitionType(type));

      boolean openInForeground =
          mOrderController.willOpenInForeground(type, mIncognito) || webContents != null;
      ChromeTab tab;
      if (webContents != null) {
        tab =
            ChromeTab.createLiveTab(
                Tab.INVALID_TAB_ID,
                mActivity,
                mIncognito,
                mNativeWindow,
                type,
                parentId,
                !openInForeground);
        tab.initialize(webContents, mTabContentManager, !openInForeground);
        tab.getTabRedirectHandler().updateIntent(intent);

        if (isWebContentsPaused) webContents.resumeLoadingCreatedWebContents();
      } else if (!openInForeground && SysUtils.isLowEndDevice()) {
        // On low memory devices the tabs opened in background are not loaded automatically
        // to preserve resources (cpu, memory, strong renderer binding) for the foreground
        // tab.
        tab =
            ChromeTab.createTabForLazyLoad(
                mActivity, mIncognito, mNativeWindow, type, parentId, loadUrlParams);
        tab.initialize(null, mTabContentManager, !openInForeground);
        mTabSaver.addTabToSaveQueue(tab);
        tab.getTabRedirectHandler().updateIntent(intent);
      } else {
        tab =
            ChromeTab.createLiveTab(
                Tab.INVALID_TAB_ID,
                mActivity,
                mIncognito,
                mNativeWindow,
                type,
                parentId,
                !openInForeground);

        webContents =
            WarmupManager.getInstance().hasPrerenderedUrl(loadUrlParams.getUrl())
                ? WarmupManager.getInstance().takePrerenderedWebContents()
                : null;
        tab.initialize(webContents, mTabContentManager, !openInForeground);
        tab.getTabRedirectHandler().updateIntent(intent);
        tab.loadUrl(loadUrlParams);
      }

      if (intent != null && intent.hasExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA)) {
        ServiceTabLauncher.onWebContentsForRequestAvailable(
            intent.getIntExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, 0),
            tab.getWebContents());
      }

      mTabModel.addTab(tab, position, type);

      return tab;
    } finally {
      TraceEvent.end("ChromeTabCreator.createNewTab");
    }
  }