public void init() { int iconSize = mContext.getResources().getDimensionPixelSize(R.dimen.abouthome_addon_icon_size); sIconBounds = new Rect(0, 0, iconSize, iconSize); sSubTitleSpan = new TextAppearanceSpan(mContext, R.style.AboutHome_TextAppearance_SubTitle); inflate(); mAccountManager = AccountManager.get(mContext); // The listener will run on the background thread (see 2nd argument) mAccountManager.addOnAccountsUpdatedListener( mAccountListener = new OnAccountsUpdateListener() { public void onAccountsUpdated(Account[] accounts) { updateLayoutForSync(); } }, GeckoAppShell.getHandler(), false); mRemoteTabClickListener = new View.OnClickListener() { @Override public void onClick(View v) { int flags = Tabs.LOADURL_NEW_TAB; if (Tabs.getInstance().getSelectedTab().isPrivate()) flags |= Tabs.LOADURL_PRIVATE; Tabs.getInstance().loadUrl((String) v.getTag(), flags); } }; mPrelimPromoBoxType = (new Random()).nextFloat() < 0.5 ? AboutHomePromoBox.Type.SYNC : AboutHomePromoBox.Type.APPS; }
/* * If the app has been launched a certain number of times, and we haven't asked for feedback before, * open a new tab with about:feedback when launching the app from the icon shortcut. */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (!Intent.ACTION_MAIN.equals(intent.getAction()) || !mInitialized) return; (new GeckoAsyncTask<Void, Void, Boolean>(mAppContext, GeckoAppShell.getHandler()) { @Override public synchronized Boolean doInBackground(Void... params) { // Check to see how many times the app has been launched. SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE); String keyName = getPackageName() + ".feedback_launch_count"; int launchCount = settings.getInt(keyName, 0); if (launchCount >= FEEDBACK_LAUNCH_COUNT) return false; // Increment the launch count and store the new value. launchCount++; settings.edit().putInt(keyName, launchCount).commit(); // If we've reached our magic number, show the feedback page. return launchCount == FEEDBACK_LAUNCH_COUNT; } @Override public void onPostExecute(Boolean shouldShowFeedbackPage) { if (shouldShowFeedbackPage) Tabs.getInstance().loadUrlInTab("about:feedback"); } }) .execute(); }
protected void onPostExecute(Pair<GroupList, List<ChildrenList>> result) { mCursorAdapter = new HistoryListAdapter( mContext, result.first, R.layout.awesomebar_header_row, new String[] {URLColumns.TITLE}, new int[] {R.id.title}, result.second); if (mContentObserver == null) { // Register an observer to update the history tab contents if they change. mContentObserver = new ContentObserver(GeckoAppShell.getHandler()) { public void onChange(boolean selfChange) { mQueryTask = new HistoryQueryTask(); mQueryTask.execute(); } }; BrowserDB.registerHistoryObserver(getContentResolver(), mContentObserver); } final ExpandableListView historyList = (ExpandableListView) getView(); // Hack: force this to the main thread, even though it should already be on it GeckoApp.mAppContext.mMainHandler.post( new Runnable() { public void run() { historyList.setAdapter(mCursorAdapter); expandAllGroups(historyList); } }); mQueryTask = null; }
public void unpinAllSites() { final ContentResolver resolver = mActivity.getContentResolver(); // Clear the view quickly to make things appear responsive for (int i = 0; i < mTopSitesGrid.getChildCount(); i++) { View v = mTopSitesGrid.getChildAt(i); TopSitesViewHolder holder = (TopSitesViewHolder) v.getTag(); clearThumbnail(holder); } (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { ContentResolver resolver = mActivity.getContentResolver(); BrowserDB.unpinAllSites(resolver); return null; } @Override public void onPostExecute(Void v) { update(EnumSet.of(UpdateFlags.TOP_SITES)); } }) .execute(); }
// Helper method to check if there are any clients available public static void areClientsAvailable( final Context context, final OnClientsAvailableListener listener) { if (listener == null) return; (new GeckoAsyncTask<Void, Void, Boolean>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override protected Boolean doInBackground(Void... unused) { Uri uri = BrowserContract.Tabs.CONTENT_URI; uri = uri.buildUpon().appendQueryParameter(BrowserContract.PARAM_LIMIT, "1").build(); Cursor cursor = context .getContentResolver() .query(uri, CLIENTS_AVAILABILITY_PROJECTION, CLIENTS_SELECTION, null, null); if (cursor == null) return false; try { return cursor.moveToNext(); } finally { cursor.close(); } } @Override protected void onPostExecute(Boolean availability) { listener.areAvailable(availability); } }) .setPriority(GeckoAsyncTask.Priority.HIGH) .execute(); }
public void init() { int iconSize = mContext.getResources().getDimensionPixelSize(R.dimen.abouthome_addon_icon_size); sIconBounds = new Rect(0, 0, iconSize, iconSize); sSubTitleSpan = new TextAppearanceSpan(mContext, R.style.AboutHome_TextAppearance_SubTitle); inflate(); // Reload the mobile homepage on inbound tab syncs // Because the tabs URI is coarse grained, this updates the // remote tabs component on *every* tab change // The observer will run on the background thread (see constructor argument) mTabsContentObserver = new ContentObserver(GeckoAppShell.getHandler()) { public void onChange(boolean selfChange) { update(EnumSet.of(AboutHomeContent.UpdateFlags.REMOTE_TABS)); } }; mActivity .getContentResolver() .registerContentObserver(BrowserContract.Tabs.CONTENT_URI, false, mTabsContentObserver); mRemoteTabClickListener = new View.OnClickListener() { @Override public void onClick(View v) { int flags = Tabs.LOADURL_NEW_TAB; if (Tabs.getInstance().getSelectedTab().isPrivate()) flags |= Tabs.LOADURL_PRIVATE; Tabs.getInstance().loadUrl((String) v.getTag(), flags); } }; }
public void init() { inflate(); mAccountManager = AccountManager.get(mContext); // The listener will run on the background thread (see 2nd argument) mAccountManager.addOnAccountsUpdatedListener( mAccountListener = new OnAccountsUpdateListener() { public void onAccountsUpdated(Account[] accounts) { updateLayoutForSync(); } }, GeckoAppShell.getHandler(), false); mRemoteTabClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Tabs.getInstance().loadUrl((String) v.getTag(), Tabs.LOADURL_NEW_TAB); } }; mPrelimPromoBoxType = (new Random()).nextFloat() < 0.5 ? AboutHomePromoBox.Type.SYNC : AboutHomePromoBox.Type.APPS; }
public void pinSite() { final int position = mTopSitesGrid.getSelectedPosition(); View v = mTopSitesGrid.getChildAt(position); TopSitesViewHolder holder = (TopSitesViewHolder) v.getTag(); final String url = holder.url; final String title = holder.titleView.getText().toString(); holder.setPinned(true); // update the database on a background thread (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { final ContentResolver resolver = mActivity.getContentResolver(); BrowserDB.pinSite( resolver, url, (title == null || TextUtils.isEmpty(title) ? url : title), position); return null; } @Override public void onPostExecute(Void v) { update(EnumSet.of(UpdateFlags.TOP_SITES)); } }) .execute(); }
// GeckoEventListener implementation public void handleMessage(String event, final JSONObject message) { GeckoAppShell.getHandler() .post( new Runnable() { public void run() { processMessage(message); } }); }
/** Query for suggestions, but don't show them yet. */ private void primeSuggestions() { GeckoAppShell.getHandler() .post( new Runnable() { @Override public void run() { mSuggestClient.query(mSearchTerm); } }); }
// This method returns limited number of tabs from all remote clients, // ordered by most recent client first, most recent tab first public static void getTabs( final Context context, final int limit, final OnQueryTabsCompleteListener listener) { // If there is no listener, no point in doing work. if (listener == null) return; (new GeckoAsyncTask<Void, Void, List<RemoteTab>>( GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override protected List<RemoteTab> doInBackground(Void... unused) { Uri uri = BrowserContract.Tabs.CONTENT_URI; if (limit > 0) { uri = uri.buildUpon() .appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit)) .build(); } Cursor cursor = context .getContentResolver() .query(uri, TABS_PROJECTION_COLUMNS, TABS_SELECTION, null, null); if (cursor == null) return null; RemoteTab tab; final ArrayList<RemoteTab> tabs = new ArrayList<RemoteTab>(); try { while (cursor.moveToNext()) { tab = new RemoteTab(); tab.title = cursor.getString(TABS_COLUMN.TITLE.ordinal()); tab.url = cursor.getString(TABS_COLUMN.URL.ordinal()); tab.guid = cursor.getString(TABS_COLUMN.GUID.ordinal()); tab.name = cursor.getString(TABS_COLUMN.NAME.ordinal()); tabs.add(tab); } } finally { cursor.close(); } return Collections.unmodifiableList(tabs); } @Override protected void onPostExecute(List<RemoteTab> tabs) { listener.onQueryTabsComplete(tabs); } }) .execute(); }
void update(final EnumSet<UpdateFlags> flags) { GeckoAppShell.getHandler() .post( new Runnable() { public void run() { if (flags.contains(UpdateFlags.TOP_SITES)) loadTopSites(); if (flags.contains(UpdateFlags.PREVIOUS_TABS)) readLastTabs(); if (flags.contains(UpdateFlags.RECOMMENDED_ADDONS)) readRecommendedAddons(); if (flags.contains(UpdateFlags.REMOTE_TABS)) loadRemoteTabs(); } }); }
private void loadTopSitesThumbnails(final ContentResolver cr) { final List<String> urls = getTopSitesUrls(); if (urls.size() == 0) return; (new GeckoAsyncTask<Void, Void, Cursor>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Cursor doInBackground(Void... params) { return BrowserDB.getThumbnailsForUrls(cr, urls); } @Override public void onPostExecute(Cursor c) { updateTopSitesThumbnails(getThumbnailsFromCursor(c)); } }) .execute(); }
private void loadFaviconsForCurrentResults() { final List<String> urls = getUrlsWithoutFavicon(); if (urls.size() == 0) return; (new UiAsyncTask<Void, Void, Cursor>(GeckoAppShell.getHandler()) { @Override public Cursor doInBackground(Void... params) { return BrowserDB.getFaviconsForUrls(getContentResolver(), urls); } @Override public void onPostExecute(Cursor c) { storeFaviconsInMemCache(c); postUpdateFavicons(); } }) .execute(); }
public void pinSite() { final int position = mTopSitesGrid.getSelectedPosition(); View v = mTopSitesGrid.getChildAt(position); final TopSitesViewHolder holder = (TopSitesViewHolder) v.getTag(); holder.setPinned(true); // update the database on a background thread (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { final ContentResolver resolver = mActivity.getContentResolver(); BrowserDB.pinSite(resolver, holder.getUrl(), holder.getTitle(), position); return null; } }) .execute(); }
public void unpinSite(final UnpinFlags flags) { final int position = mTopSitesGrid.getSelectedPosition(); final View v = mTopSitesGrid.getChildAt(position); final TopSitesViewHolder holder = (TopSitesViewHolder) v.getTag(); final String url = holder.getUrl(); // Quickly update the view so that there isn't as much lag between the request and response clearThumbnail(holder); (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { final ContentResolver resolver = mActivity.getContentResolver(); BrowserDB.unpinSite(resolver, position); if (flags == UnpinFlags.REMOVE_HISTORY) { BrowserDB.removeHistoryEntry(resolver, url); } return null; } }) .execute(); }
@Override protected void onDialogClosed(boolean positiveResult) { if (!positiveResult) { // user cancelled; reset checkbox values to their previous state mValues = mPrevValues.clone(); return; } else { mPrevValues = mValues.clone(); } GeckoAppShell.getHandler() .post( new Runnable() { public void run() { for (int i = 0; i < mEntryKeys.length; i++) { String key = mEntryKeys[i].toString(); persistBoolean(key, mValues[i]); } } }); }
public void unpinSite() { final int position = mTopSitesGrid.getSelectedPosition(); View v = mTopSitesGrid.getChildAt(position); TopSitesViewHolder holder = (TopSitesViewHolder) v.getTag(); // Quickly update the view so that there isn't as much lag between the request and response clearThumbnail(holder); (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { ContentResolver resolver = mActivity.getContentResolver(); BrowserDB.unpinSite(resolver, position); return null; } @Override public void onPostExecute(Void v) { update(EnumSet.of(UpdateFlags.TOP_SITES)); } }) .execute(); }
/** * Loads persistent prefs from shared preferences. If the preferences aren't persistent or haven't * yet been stored, they will be set to their initial values. */ private void loadPersistedValues() { if (mEntryKeys == null || mInitialValues == null) return; final int entryCount = mEntryKeys.length; if (entryCount != mEntries.length || entryCount != mInitialValues.length) { throw new IllegalStateException( "MultiChoicePreference entryKeys and initialValues arrays must be the same length"); } mValues = new boolean[entryCount]; GeckoAppShell.getHandler() .post( new Runnable() { public void run() { for (int i = 0; i < entryCount; i++) { String key = mEntryKeys[i].toString(); boolean initialValue = mInitialValues[i].equals("true"); mValues[i] = getPersistedBoolean(key, initialValue); } mPrevValues = mValues.clone(); } }); }
private void getLastUrl() { (new GeckoAsyncTask<Void, Void, String>(mAppContext, GeckoAppShell.getHandler()) { @Override public synchronized String doInBackground(Void... params) { // Get the most recent URL stored in browser history. String url = ""; Cursor c = BrowserDB.getRecentHistory(getContentResolver(), 1); if (c.moveToFirst()) { url = c.getString(c.getColumnIndexOrThrow(Combined.URL)); } c.close(); return url; } @Override public void onPostExecute(String url) { // Don't bother sending a message if there is no URL. if (url.length() > 0) GeckoAppShell.sendEventToGecko( GeckoEvent.createBroadcastEvent("Feedback:LastUrl", url)); } }) .execute(); }
private void addAddonMenuItem(final MenuItemInfo info) { if (mMenu == null) { if (mAddonMenuItemsCache == null) mAddonMenuItemsCache = new Vector<MenuItemInfo>(); mAddonMenuItemsCache.add(info); return; } Menu menu; if (info.parent == 0) { menu = mMenu; } else { MenuItem parent = mMenu.findItem(info.parent); if (parent == null) return; if (!parent.hasSubMenu()) { mMenu.removeItem(parent.getItemId()); menu = mMenu.addSubMenu(Menu.NONE, parent.getItemId(), Menu.NONE, parent.getTitle()); if (parent.getIcon() != null) ((SubMenu) menu).getItem().setIcon(parent.getIcon()); } else { menu = parent.getSubMenu(); } } final MenuItem item = menu.add(Menu.NONE, info.id, Menu.NONE, info.label); item.setOnMenuItemClickListener( new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { Log.i(LOGTAG, "menu item clicked"); GeckoAppShell.sendEventToGecko( GeckoEvent.createBroadcastEvent( "Menu:Clicked", Integer.toString(info.id - ADDON_MENU_OFFSET))); return true; } }); if (info.icon != null) { if (info.icon.startsWith("data")) { BitmapDrawable drawable = new BitmapDrawable(BitmapUtils.getBitmapFromDataURI(info.icon)); item.setIcon(drawable); } else if (info.icon.startsWith("jar:") || info.icon.startsWith("file://")) { GeckoAppShell.getHandler() .post( new Runnable() { public void run() { try { URL url = new URL(info.icon); InputStream is = (InputStream) url.getContent(); try { Drawable drawable = Drawable.createFromStream(is, "src"); item.setIcon(drawable); } finally { is.close(); } } catch (Exception e) { Log.w(LOGTAG, "Unable to set icon", e); } } }); } } item.setCheckable(info.checkable); item.setChecked(info.checked); item.setEnabled(info.enabled); item.setVisible(info.visible); }
@Override public boolean onContextItemSelected(MenuItem item) { if (mContextMenuSubject == null) return false; final int id = mContextMenuSubject.id; final String url = mContextMenuSubject.url; final byte[] b = mContextMenuSubject.favicon; final String title = mContextMenuSubject.title; final String keyword = mContextMenuSubject.keyword; switch (item.getItemId()) { case R.id.open_new_tab: { if (url == null) { Log.e(LOGTAG, "Can't open in new tab because URL is null"); break; } GeckoApp.mAppContext.loadUrl(url, AwesomeBar.Target.NEW_TAB); Toast.makeText(this, R.string.new_tab_opened, Toast.LENGTH_SHORT).show(); break; } case R.id.open_in_reader: { if (url == null) { Log.e(LOGTAG, "Can't open in reader mode because URL is null"); break; } openUrlAndFinish(ReaderModeUtils.getAboutReaderForUrl(url, true)); break; } case R.id.edit_bookmark: { AlertDialog.Builder editPrompt = new AlertDialog.Builder(this); View editView = getLayoutInflater().inflate(R.layout.bookmark_edit, null); editPrompt.setTitle(R.string.bookmark_edit_title); editPrompt.setView(editView); final EditText nameText = ((EditText) editView.findViewById(R.id.edit_bookmark_name)); final EditText locationText = ((EditText) editView.findViewById(R.id.edit_bookmark_location)); final EditText keywordText = ((EditText) editView.findViewById(R.id.edit_bookmark_keyword)); nameText.setText(title); locationText.setText(url); keywordText.setText(keyword); editPrompt.setPositiveButton( R.string.button_ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { (new GeckoAsyncTask<Void, Void, Void>( GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { String newUrl = locationText.getText().toString().trim(); BrowserDB.updateBookmark( mResolver, id, newUrl, nameText.getText().toString(), keywordText.getText().toString()); return null; } @Override public void onPostExecute(Void result) { Toast.makeText( AwesomeBar.this, R.string.bookmark_updated, Toast.LENGTH_SHORT) .show(); } }) .execute(); } }); editPrompt.setNegativeButton( R.string.button_cancel, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // do nothing } }); final AlertDialog dialog = editPrompt.create(); // disable OK button if the URL is empty locationText.addTextChangedListener( new TextWatcher() { private boolean mEnabled = true; public void afterTextChanged(Editable s) {} public void beforeTextChanged(CharSequence s, int start, int count, int after) {} public void onTextChanged(CharSequence s, int start, int before, int count) { boolean enabled = (s.toString().trim().length() > 0); if (mEnabled != enabled) { dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(enabled); mEnabled = enabled; } } }); dialog.show(); break; } case R.id.remove_bookmark: { (new AsyncTask<Void, Void, Void>() { private boolean mInReadingList; @Override public void onPreExecute() { mInReadingList = mAwesomeTabs.isInReadingList(); } @Override public Void doInBackground(Void... params) { BrowserDB.removeBookmark(mResolver, id); return null; } @Override public void onPostExecute(Void result) { int messageId = R.string.bookmark_removed; if (mInReadingList) { messageId = R.string.reading_list_removed; GeckoEvent e = GeckoEvent.createBroadcastEvent("Reader:Remove", url); GeckoAppShell.sendEventToGecko(e); } Toast.makeText(AwesomeBar.this, messageId, Toast.LENGTH_SHORT).show(); } }) .execute(); break; } case R.id.remove_history: { (new GeckoAsyncTask<Void, Void, Void>(GeckoApp.mAppContext, GeckoAppShell.getHandler()) { @Override public Void doInBackground(Void... params) { BrowserDB.removeHistoryEntry(mResolver, id); return null; } @Override public void onPostExecute(Void result) { Toast.makeText(AwesomeBar.this, R.string.history_removed, Toast.LENGTH_SHORT) .show(); } }) .execute(); break; } case R.id.add_to_launcher: { if (url == null) { Log.e(LOGTAG, "Can't add to home screen because URL is null"); break; } Bitmap bitmap = null; if (b != null) bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); String shortcutTitle = TextUtils.isEmpty(title) ? url.replaceAll("^([a-z]+://)?(www\\.)?", "") : title; GeckoAppShell.createShortcut(shortcutTitle, url, bitmap, ""); break; } case R.id.share: { if (url == null) { Log.e(LOGTAG, "Can't share because URL is null"); break; } GeckoAppShell.openUriExternal(url, "text/plain", "", "", Intent.ACTION_SEND, title); break; } default: { return super.onContextItemSelected(item); } } return true; }