// This callback is automatically executed on the UI thread. @Override public void onTabChanged(final Tab tab, final Tabs.TabEvents msg, final Object data) { switch (msg) { case CLOSED: // Remove any doorhangers for a tab when it's closed (make // a temporary set to avoid a ConcurrentModificationException) HashSet<DoorHanger> doorHangersToRemove = new HashSet<DoorHanger>(); for (DoorHanger dh : mDoorHangers) { if (dh.getTabId() == tab.getId()) doorHangersToRemove.add(dh); } for (DoorHanger dh : doorHangersToRemove) { removeDoorHanger(dh); } break; case LOCATION_CHANGE: // Only remove doorhangers if the popup is hidden or if we're navigating to a new URL if (!isShowing() || !data.equals(tab.getURL())) removeTransientDoorHangers(tab.getId()); // Update the popup if the location change was on the current tab if (Tabs.getInstance().isSelectedTab(tab)) updatePopup(); break; case SELECTED: // Always update the popup when a new tab is selected. This will cover cases // where a different tab was closed, since we always need to select a new tab. updatePopup(); break; } }
/** * Gets a doorhanger. * * <p>This method must be called on the UI thread. */ DoorHanger getDoorHanger(int tabId, String value) { for (DoorHanger dh : mDoorHangers) { if (dh.getTabId() == tabId && dh.getValue().equals(value)) return dh; } // If there's no doorhanger for the given tabId and value, return null return null; }
/** * Removes doorhangers for a given tab. * * <p>This method must be called on the UI thread. */ void removeTransientDoorHangers(int tabId) { // Make a temporary set to avoid a ConcurrentModificationException HashSet<DoorHanger> doorHangersToRemove = new HashSet<DoorHanger>(); for (DoorHanger dh : mDoorHangers) { // Only remove transient doorhangers for the given tab if (dh.getTabId() == tabId && dh.shouldRemove(isShowing())) doorHangersToRemove.add(dh); } for (DoorHanger dh : doorHangersToRemove) { removeDoorHanger(dh); } }
/** * Updates the popup state. * * <p>This method must be called on the UI thread. */ void updatePopup() { // Bail if the selected tab is null, if there are no active doorhangers, // if we haven't inflated the layout yet (this can happen if updatePopup() // is called before the runnable from addDoorHanger() runs), or if the // doorhanger popup is temporarily disabled. Tab tab = Tabs.getInstance().getSelectedTab(); if (tab == null || mDoorHangers.size() == 0 || !mInflated || mDisabled) { dismiss(); return; } // Show doorhangers for the selected tab int tabId = tab.getId(); boolean shouldShowPopup = false; for (DoorHanger dh : mDoorHangers) { if (dh.getTabId() == tabId) { dh.setVisibility(View.VISIBLE); shouldShowPopup = true; } else { dh.setVisibility(View.GONE); } } // Dismiss the popup if there are no doorhangers to show for this tab if (!shouldShowPopup) { dismiss(); return; } showDividers(); if (isShowing()) { show(); return; } // Make the popup focusable for accessibility. This gets done here // so the node can be accessibility focused, but on pre-ICS devices this // causes crashes, so it is done after the popup is shown. if (Build.VERSION.SDK_INT >= 14) { setFocusable(true); } show(); if (Build.VERSION.SDK_INT < 14) { // Make the popup focusable for keyboard accessibility. setFocusable(true); } }