Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.bookmarkswidget; | 5 package org.chromium.chrome.browser.bookmarkswidget; |
| 6 | 6 |
| 7 import android.appwidget.AppWidgetManager; | 7 import android.appwidget.AppWidgetManager; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.Intent; | 9 import android.content.Intent; |
| 10 import android.content.SharedPreferences; | 10 import android.content.SharedPreferences; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 import org.chromium.base.metrics.RecordUserAction; | 28 import org.chromium.base.metrics.RecordUserAction; |
| 29 import org.chromium.chrome.R; | 29 import org.chromium.chrome.R; |
| 30 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; | 30 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; |
| 31 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserve r; | 31 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserve r; |
| 32 import org.chromium.chrome.browser.bookmarks.BookmarkModel; | 32 import org.chromium.chrome.browser.bookmarks.BookmarkModel; |
| 33 import org.chromium.chrome.browser.favicon.LargeIconBridge; | 33 import org.chromium.chrome.browser.favicon.LargeIconBridge; |
| 34 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; | 34 import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback; |
| 35 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; | 35 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
| 36 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; | 36 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim; |
| 37 import org.chromium.chrome.browser.profiles.Profile; | 37 import org.chromium.chrome.browser.profiles.Profile; |
| 38 import org.chromium.chrome.browser.tab.Tab; | |
| 39 import org.chromium.chrome.browser.util.IntentUtils; | 38 import org.chromium.chrome.browser.util.IntentUtils; |
| 40 import org.chromium.chrome.browser.widget.RoundedIconGenerator; | 39 import org.chromium.chrome.browser.widget.RoundedIconGenerator; |
| 41 import org.chromium.components.bookmarks.BookmarkId; | 40 import org.chromium.components.bookmarks.BookmarkId; |
| 42 import org.chromium.components.bookmarks.BookmarkType; | |
| 43 | 41 |
| 44 import java.util.ArrayList; | 42 import java.util.ArrayList; |
| 45 import java.util.Collections; | 43 import java.util.Collections; |
| 46 import java.util.Comparator; | 44 import java.util.Comparator; |
| 47 import java.util.List; | 45 import java.util.List; |
| 48 import java.util.concurrent.LinkedBlockingQueue; | 46 import java.util.concurrent.LinkedBlockingQueue; |
| 49 | 47 |
| 50 import javax.annotation.Nullable; | 48 import javax.annotation.Nullable; |
| 51 | 49 |
| 52 /** | 50 /** |
| 53 * Service to support the bookmarks widget. | 51 * Service to support the bookmarks widget. |
| 54 * | 52 * |
| 55 * This provides the list of bookmarks to show in the widget via a RemoteViewsFa ctory (the | 53 * This provides the list of bookmarks to show in the widget via a RemoteViewsFa ctory (the |
| 56 * RemoteViews equivalent of an Adapter), and updates the widget when the bookma rk model changes. | 54 * RemoteViews equivalent of an Adapter), and updates the widget when the bookma rk model changes. |
| 57 * | 55 * |
| 58 * Threading note: Be careful! Android calls some methods in this class on the U I thread and others | 56 * Threading note: Be careful! Android calls some methods in this class on the U I thread and others |
| 59 * on (multiple) binder threads. Additionally, all interaction with the Bookmark Model must happen on | 57 * on (multiple) binder threads. Additionally, all interaction with the Bookmark Model must happen on |
| 60 * the UI thread. To keep the situation clear, every non-static method is annota ted with either | 58 * the UI thread. To keep the situation clear, every non-static method is annota ted with either |
| 61 * {@link UiThread} or {@link BinderThread}. | 59 * {@link UiThread} or {@link BinderThread}. |
| 62 */ | 60 */ |
| 63 public class BookmarkWidgetService extends RemoteViewsService { | 61 public class BookmarkWidgetService extends RemoteViewsService { |
| 64 | 62 |
| 65 private static final String TAG = "BookmarkWidget"; | 63 private static final String TAG = "BookmarkWidget"; |
| 66 private static final String ACTION_CHANGE_FOLDER_SUFFIX = ".CHANGE_FOLDER"; | 64 private static final String ACTION_CHANGE_FOLDER_SUFFIX = ".CHANGE_FOLDER"; |
| 67 private static final String PREF_CURRENT_FOLDER = "current_folder"; | 65 private static final String PREF_CURRENT_FOLDER = "bookmarkswidget.current_f older"; |
|
Ted C
2016/06/03 03:16:39
has this pref ever changed? did it change when we
| |
| 68 private static final String EXTRA_FOLDER_ID = "folderId"; | 66 private static final String EXTRA_FOLDER_ID = "folderId"; |
| 69 | 67 |
| 70 @UiThread | 68 @UiThread |
| 71 @Override | 69 @Override |
| 72 public RemoteViewsFactory onGetViewFactory(Intent intent) { | 70 public RemoteViewsFactory onGetViewFactory(Intent intent) { |
| 73 int widgetId = IntentUtils.safeGetIntExtra(intent, AppWidgetManager.EXTR A_APPWIDGET_ID, -1); | 71 int widgetId = IntentUtils.safeGetIntExtra(intent, AppWidgetManager.EXTR A_APPWIDGET_ID, -1); |
| 74 if (widgetId < 0) { | 72 if (widgetId < 0) { |
| 75 Log.w(TAG, "Missing EXTRA_APPWIDGET_ID!"); | 73 Log.w(TAG, "Missing EXTRA_APPWIDGET_ID!"); |
| 76 return null; | 74 return null; |
| 77 } | 75 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 94 } | 92 } |
| 95 } | 93 } |
| 96 | 94 |
| 97 static void deleteWidgetState(Context context, int widgetId) { | 95 static void deleteWidgetState(Context context, int widgetId) { |
| 98 SharedPreferences preferences = getWidgetState(context, widgetId); | 96 SharedPreferences preferences = getWidgetState(context, widgetId); |
| 99 if (preferences != null) preferences.edit().clear().apply(); | 97 if (preferences != null) preferences.edit().clear().apply(); |
| 100 } | 98 } |
| 101 | 99 |
| 102 static void changeFolder(Context context, Intent intent) { | 100 static void changeFolder(Context context, Intent intent) { |
| 103 int widgetId = IntentUtils.safeGetIntExtra(intent, AppWidgetManager.EXTR A_APPWIDGET_ID, -1); | 101 int widgetId = IntentUtils.safeGetIntExtra(intent, AppWidgetManager.EXTR A_APPWIDGET_ID, -1); |
| 104 long folderId = IntentUtils.safeGetLongExtra(intent, EXTRA_FOLDER_ID, -1 ); | 102 String serializedFolder = IntentUtils.safeGetStringExtra(intent, EXTRA_F OLDER_ID); |
| 105 if (widgetId >= 0 && folderId >= 0) { | 103 if (widgetId >= 0 && serializedFolder != null) { |
| 106 SharedPreferences prefs = getWidgetState(context, widgetId); | 104 SharedPreferences prefs = getWidgetState(context, widgetId); |
| 107 prefs.edit().putLong(PREF_CURRENT_FOLDER, folderId).apply(); | 105 prefs.edit().putString(PREF_CURRENT_FOLDER, serializedFolder).apply( ); |
| 108 AppWidgetManager.getInstance(context) | 106 AppWidgetManager.getInstance(context) |
| 109 .notifyAppWidgetViewDataChanged(widgetId, R.id.bookmarks_lis t); | 107 .notifyAppWidgetViewDataChanged(widgetId, R.id.bookmarks_lis t); |
| 110 } | 108 } |
| 111 } | 109 } |
| 112 | 110 |
| 113 /** | 111 /** |
| 114 * Holds data describing a bookmark or bookmark folder. | 112 * Holds data describing a bookmark or bookmark folder. |
| 115 */ | 113 */ |
| 116 private static class Bookmark { | 114 private static class Bookmark { |
| 117 public String title; | 115 public String title; |
| 118 public String url; | 116 public String url; |
| 119 public BookmarkId id; | 117 public BookmarkId id; |
| 120 public BookmarkId parentId; | 118 public BookmarkId parentId; |
| 121 public boolean isFolder; | 119 public boolean isFolder; |
| 122 public Bitmap favicon; | 120 public Bitmap favicon; |
| 123 | 121 |
| 124 public static Bookmark fromBookmarkItem(BookmarkItem item) { | 122 public static Bookmark fromBookmarkItem(BookmarkItem item) { |
| 125 if (item == null) return null; | 123 if (item == null) return null; |
| 126 | 124 |
| 127 // The bookmarks widget doesn't support showing partner bookmarks. T he main hurdle is | |
| 128 // that the current folder ID is stored in shared prefs as a long, n ot a BookmarkId. | |
| 129 // This support could be added if there's a strong desire. | |
| 130 if (item.getId().getType() == BookmarkType.PARTNER) return null; | |
| 131 | |
| 132 Bookmark bookmark = new Bookmark(); | 125 Bookmark bookmark = new Bookmark(); |
| 133 bookmark.title = item.getTitle(); | 126 bookmark.title = item.getTitle(); |
| 134 bookmark.url = item.getUrl(); | 127 bookmark.url = item.getUrl(); |
| 135 bookmark.id = item.getId(); | 128 bookmark.id = item.getId(); |
| 136 bookmark.parentId = item.getParentId(); | 129 bookmark.parentId = item.getParentId(); |
| 137 bookmark.isFolder = item.isFolder(); | 130 bookmark.isFolder = item.isFolder(); |
| 138 return bookmark; | 131 return bookmark; |
| 139 } | 132 } |
| 140 } | 133 } |
| 141 | 134 |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 326 public void bookmarkModelChanged() { | 319 public void bookmarkModelChanged() { |
| 327 refreshWidget(); | 320 refreshWidget(); |
| 328 } | 321 } |
| 329 }); | 322 }); |
| 330 } | 323 } |
| 331 | 324 |
| 332 @UiThread | 325 @UiThread |
| 333 private boolean isWidgetNewlyCreated() { | 326 private boolean isWidgetNewlyCreated() { |
| 334 // This method relies on the fact that PREF_CURRENT_FOLDER is not ye t | 327 // This method relies on the fact that PREF_CURRENT_FOLDER is not ye t |
| 335 // set when onCreate is called for a newly created widget. | 328 // set when onCreate is called for a newly created widget. |
| 336 long currentFolder = mPreferences.getLong(PREF_CURRENT_FOLDER, Tab.I NVALID_BOOKMARK_ID); | 329 String serializedFolder = mPreferences.getString(PREF_CURRENT_FOLDER , null); |
| 337 return currentFolder == Tab.INVALID_BOOKMARK_ID; | 330 return serializedFolder == null; |
| 338 } | 331 } |
| 339 | 332 |
| 340 @UiThread | 333 @UiThread |
| 341 private void refreshWidget() { | 334 private void refreshWidget() { |
| 342 mContext.sendBroadcast(new Intent( | 335 mContext.sendBroadcast(new Intent( |
| 343 BookmarkWidgetProvider.getBookmarkAppWidgetUpdateAction(mCon text), | 336 BookmarkWidgetProvider.getBookmarkAppWidgetUpdateAction(mCon text), |
| 344 null, mContext, BookmarkThumbnailWidgetProvider.class) | 337 null, mContext, BookmarkThumbnailWidgetProvider.class) |
| 345 .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId)); | 338 .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId)); |
| 346 } | 339 } |
| 347 | 340 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 367 } | 360 } |
| 368 | 361 |
| 369 @BinderThread | 362 @BinderThread |
| 370 @Override | 363 @Override |
| 371 public void onDataSetChanged() { | 364 public void onDataSetChanged() { |
| 372 updateBookmarkList(); | 365 updateBookmarkList(); |
| 373 } | 366 } |
| 374 | 367 |
| 375 @BinderThread | 368 @BinderThread |
| 376 private void updateBookmarkList() { | 369 private void updateBookmarkList() { |
| 377 long folderIdLong = mPreferences.getLong(PREF_CURRENT_FOLDER, Tab.IN VALID_BOOKMARK_ID); | 370 BookmarkId folderId = BookmarkId |
| 378 BookmarkId folderId = folderIdLong != Tab.INVALID_BOOKMARK_ID | 371 .getBookmarkIdFromString(mPreferences.getString(PREF_CURRENT _FOLDER, null)); |
| 379 ? new BookmarkId(folderIdLong, BookmarkType.NORMAL) | |
| 380 : null; | |
| 381 | |
| 382 mCurrentFolder = loadBookmarks(folderId); | 372 mCurrentFolder = loadBookmarks(folderId); |
| 383 | 373 mPreferences.edit().putString(PREF_CURRENT_FOLDER, mCurrentFolder.fo lder.id.toString()) |
| 384 mPreferences.edit() | 374 .apply(); |
| 385 .putLong(PREF_CURRENT_FOLDER, mCurrentFolder != null | |
| 386 ? mCurrentFolder.folder.id.getId() | |
| 387 : Tab.INVALID_BOOKMARK_ID) | |
| 388 .apply(); | |
| 389 } | 375 } |
| 390 | 376 |
| 391 @BinderThread | 377 @BinderThread |
| 392 private BookmarkFolder loadBookmarks(final BookmarkId folderId) { | 378 private BookmarkFolder loadBookmarks(final BookmarkId folderId) { |
| 393 final LinkedBlockingQueue<BookmarkFolder> resultQueue = new LinkedBl ockingQueue<>(1); | 379 final LinkedBlockingQueue<BookmarkFolder> resultQueue = new LinkedBl ockingQueue<>(1); |
| 394 ThreadUtils.runOnUiThread(new Runnable() { | 380 ThreadUtils.runOnUiThread(new Runnable() { |
| 395 @Override | 381 @Override |
| 396 public void run() { | 382 public void run() { |
| 397 new BookmarkLoader(mContext, folderId, new BookmarkLoaderCal lback() { | 383 new BookmarkLoader(mContext, folderId, new BookmarkLoaderCal lback() { |
| 398 @Override | 384 @Override |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 } | 448 } |
| 463 | 449 |
| 464 Bookmark bookmark = getBookmarkForPosition(position); | 450 Bookmark bookmark = getBookmarkForPosition(position); |
| 465 if (bookmark == null) { | 451 if (bookmark == null) { |
| 466 Log.w(TAG, "Couldn't get bookmark for position %d", position); | 452 Log.w(TAG, "Couldn't get bookmark for position %d", position); |
| 467 return null; | 453 return null; |
| 468 } | 454 } |
| 469 | 455 |
| 470 String title = bookmark.title; | 456 String title = bookmark.title; |
| 471 String url = bookmark.url; | 457 String url = bookmark.url; |
| 472 long id = (bookmark == mCurrentFolder.folder) | 458 BookmarkId id = (bookmark == mCurrentFolder.folder) |
| 473 ? mCurrentFolder.parent.id.getId() | 459 ? mCurrentFolder.parent.id |
| 474 : bookmark.id.getId(); | 460 : bookmark.id; |
| 475 | 461 |
| 476 RemoteViews views = new RemoteViews(mContext.getPackageName(), | 462 RemoteViews views = new RemoteViews(mContext.getPackageName(), |
| 477 R.layout.bookmark_widget_item); | 463 R.layout.bookmark_widget_item); |
| 478 | 464 |
| 479 // Set the title of the bookmark. Use the url as a backup. | 465 // Set the title of the bookmark. Use the url as a backup. |
| 480 views.setTextViewText(R.id.title, TextUtils.isEmpty(title) ? url : t itle); | 466 views.setTextViewText(R.id.title, TextUtils.isEmpty(title) ? url : t itle); |
| 481 | 467 |
| 482 if (bookmark == mCurrentFolder.folder) { | 468 if (bookmark == mCurrentFolder.folder) { |
| 483 views.setImageViewResource(R.id.favicon, R.drawable.bookmark_bac k_normal); | 469 views.setImageViewResource(R.id.favicon, R.drawable.bookmark_bac k_normal); |
| 484 } else if (bookmark.isFolder) { | 470 } else if (bookmark.isFolder) { |
| 485 views.setImageViewResource(R.id.favicon, R.drawable.bookmark_fol der); | 471 views.setImageViewResource(R.id.favicon, R.drawable.bookmark_fol der); |
| 486 } else { | 472 } else { |
| 487 views.setImageViewBitmap(R.id.favicon, bookmark.favicon); | 473 views.setImageViewBitmap(R.id.favicon, bookmark.favicon); |
| 488 } | 474 } |
| 489 | 475 |
| 490 Intent fillIn; | 476 Intent fillIn; |
| 491 if (bookmark.isFolder) { | 477 if (bookmark.isFolder) { |
| 492 fillIn = new Intent(getChangeFolderAction(mContext)) | 478 fillIn = new Intent(getChangeFolderAction(mContext)) |
| 493 .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId ) | 479 .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId ) |
| 494 .putExtra(EXTRA_FOLDER_ID, id); | 480 .putExtra(EXTRA_FOLDER_ID, id.toString()); |
| 495 } else { | 481 } else { |
| 496 fillIn = new Intent(Intent.ACTION_VIEW); | 482 fillIn = new Intent(Intent.ACTION_VIEW); |
| 497 if (!TextUtils.isEmpty(url)) { | 483 if (!TextUtils.isEmpty(url)) { |
| 498 fillIn = fillIn.addCategory(Intent.CATEGORY_BROWSABLE) | 484 fillIn = fillIn.addCategory(Intent.CATEGORY_BROWSABLE) |
| 499 .setData(Uri.parse(url)); | 485 .setData(Uri.parse(url)); |
| 500 } else { | 486 } else { |
| 501 fillIn = fillIn.addCategory(Intent.CATEGORY_LAUNCHER); | 487 fillIn = fillIn.addCategory(Intent.CATEGORY_LAUNCHER); |
| 502 } | 488 } |
| 503 } | 489 } |
| 504 views.setOnClickFillInIntent(R.id.list_item, fillIn); | 490 views.setOnClickFillInIntent(R.id.list_item, fillIn); |
| 505 return views; | 491 return views; |
| 506 } | 492 } |
| 507 } | 493 } |
| 508 } | 494 } |
| OLD | NEW |