private static BookmarkNode createMockHierarchy() { // Mock hierarchy. // + Bookmarks // - Google // - Google maps // + Youtube // + Empty folder // + Some other folder // - Surprised Vader // - Rickroll'D BookmarkNode root = new BookmarkNode(1, Type.FOLDER, "Bookmarks", null, null); root.addChild(new BookmarkNode(2, Type.URL, "Google", "http://www.google.com/", root)); root.addChild(new BookmarkNode(3, Type.URL, "GoogleMaps", "http://maps.google.com/", root)); BookmarkNode folder1 = new BookmarkNode(4, Type.FOLDER, "Youtube", null, root); root.addChild(folder1); folder1.addChild(new BookmarkNode(5, Type.FOLDER, "Empty folder", null, folder1)); BookmarkNode folder2 = new BookmarkNode(6, Type.FOLDER, "Some other folder", null, folder1); folder1.addChild(folder2); folder1.addChild( new BookmarkNode( 7, Type.URL, "RickRoll'D", "http://www.youtube.com/watch?v=oHg5SJYRHA0", folder1)); folder2.addChild( new BookmarkNode( 8, Type.URL, "Surprised Vader", "http://www.youtube.com/watch?v=9h1swNWgP8Q", folder2)); return root; }
@SmallTest @Feature({"Android-ContentProvider"}) public void testInvalidHierarchy() throws InterruptedException { BookmarkNode root = new BookmarkNode(1, Type.FOLDER, "Bookmarks", null, null); root.addChild(new BookmarkNode(2, Type.URL, "Google", "http://www.google.com/", root)); root.addChild(new BookmarkNode(2, Type.URL, "GoogleMaps", "http://maps.google.com/", root)); assertFalse(internalTestNodeHierarchyParceling(root)); }
private BookmarkNode getBookmarkForPosition(int position) { if (mCurrentFolder == null) return null; // The position 0 is saved for an entry of the current folder used to go up. // This is not the case when the current node has no parent (it's the root node). return (mCurrentFolder.parent() == null) ? mCurrentFolder.children().get(position) : (position == 0 ? mCurrentFolder : mCurrentFolder.children().get(position - 1)); }
private static boolean isSameHierarchyDownwards(BookmarkNode n1, BookmarkNode n2) { if (n1 == null && n2 == null) return true; if (n1 == null || n2 == null) return false; if (!n1.equalContents(n2)) return false; for (int i = 0; i < n1.children().size(); ++i) { if (!isSameHierarchyDownwards(n1.children().get(i), n2.children().get(i))) return false; } return true; }
private BookmarkNode addImagesRecursive(BookmarkNode node) { node.setFavicon(mGenerator.nextBoolean() ? getRandomImageBlob() : null); node.setThumbnail(mGenerator.nextBoolean() ? getRandomImageBlob() : null); for (BookmarkNode child : node.children()) { addImagesRecursive(child); } return node; }
@Override public void onThumbnailUpdated(String url) { synchronized (mLock) { if (mCurrentFolder == null) return; for (BookmarkNode child : mCurrentFolder.children()) { if (child.isUrl() && url.equals(child.url())) { refreshWidget(); break; } } } }
private static BookmarkNode parcelNode(BookmarkNode node) { Parcel output = Parcel.obtain(); Parcel input = Parcel.obtain(); node.writeToParcel(output, 0); byte[] bytes = output.marshall(); input.unmarshall(bytes, 0, bytes.length); input.setDataPosition(0); return BookmarkNode.CREATOR.createFromParcel(input); }
// Tests parceling and comparing each of the nodes in the provided hierarchy. private boolean internalTestNodeHierarchyParceling(BookmarkNode node) { if (node == null) return false; BookmarkNode parceled = parcelNode(node); if (!isSameHierarchy(node, parceled)) return false; for (BookmarkNode child : node.children()) { if (!internalTestNodeHierarchyParceling(child)) return false; } return true; }
private BookmarkNode loadBookmarkFolder(long folderId) { if (ThreadUtils.runningOnUiThread()) { Log.e(TAG, "Trying to load bookmark folder from the UI thread."); return null; } // If the current folder id doesn't exist (it was deleted) try the current parent. // If this fails too then fallback to Mobile Bookmarks. if (!ChromeBrowserProviderClient.bookmarkNodeExists(mContext, folderId)) { folderId = mCurrentFolder != null ? getFolderId(mCurrentFolder.parent()) : ChromeBrowserProviderClient.INVALID_BOOKMARK_ID; if (!ChromeBrowserProviderClient.bookmarkNodeExists(mContext, folderId)) { folderId = ChromeBrowserProviderClient.INVALID_BOOKMARK_ID; } } // Need to verify this always because the package data might be cleared while the // widget is in the Mobile Bookmarks folder with sync enabled. In that case the // hierarchy up folder would still work (we can't update the widget) but the parent // folders should not be accessible because sync has been reset when clearing data. if (folderId != ChromeBrowserProviderClient.INVALID_BOOKMARK_ID && !AndroidSyncSettings.isSyncEnabled(mContext) && !ChromeBrowserProviderClient.isBookmarkInMobileBookmarksBranch(mContext, folderId)) { folderId = ChromeBrowserProviderClient.INVALID_BOOKMARK_ID; } // Use the Mobile Bookmarks folder by default. if (folderId < 0 || folderId == ChromeBrowserProviderClient.INVALID_BOOKMARK_ID) { folderId = ChromeBrowserProviderClient.getMobileBookmarksFolderId(mContext); if (folderId == ChromeBrowserProviderClient.INVALID_BOOKMARK_ID) return null; } return ChromeBrowserProviderClient.getBookmarkNode( mContext, folderId, ChromeBrowserProviderClient.GET_PARENT | ChromeBrowserProviderClient.GET_CHILDREN | ChromeBrowserProviderClient.GET_FAVICONS | ChromeBrowserProviderClient.GET_THUMBNAILS); }
private static long getFolderId(BookmarkNode folder) { return folder != null ? folder.id() : ChromeBrowserProviderClient.INVALID_BOOKMARK_ID; }
@Override public RemoteViews getViewAt(int position) { if (mCurrentFolder == null) { Log.w(TAG, "No current folder data available."); return null; } BookmarkNode bookmark = getBookmarkForPosition(position); if (bookmark == null) { Log.w(TAG, "Couldn't get bookmark for position " + position); return null; } if (bookmark == mCurrentFolder && bookmark.parent() == null) { Log.w(TAG, "Invalid bookmark data: loop detected."); return null; } String title = bookmark.name(); String url = bookmark.url(); long id = (bookmark == mCurrentFolder) ? bookmark.parent().id() : bookmark.id(); // Two layouts are needed because RemoteView does not supporting changing the scale type // of an ImageView: boomarks crop their thumbnails, while folders stretch their icon. RemoteViews views = !bookmark.isUrl() ? new RemoteViews( mContext.getPackageName(), R.layout.bookmark_thumbnail_widget_item_folder) : new RemoteViews(mContext.getPackageName(), R.layout.bookmark_thumbnail_widget_item); // Set the title of the bookmark. Use the url as a backup. views.setTextViewText(R.id.label, TextUtils.isEmpty(title) ? url : title); if (!bookmark.isUrl()) { int thumbId = (bookmark == mCurrentFolder) ? R.drawable.thumb_bookmark_widget_folder_back_holo : R.drawable.thumb_bookmark_widget_folder_holo; views.setImageViewResource(R.id.thumb, thumbId); views.setImageViewResource(R.id.favicon, R.drawable.ic_bookmark_widget_bookmark_holo_dark); } else { // RemoteViews require a valid bitmap config. Options options = new Options(); options.inPreferredConfig = Config.ARGB_8888; byte[] favicon = bookmark.favicon(); if (favicon != null && favicon.length > 0) { views.setImageViewBitmap( R.id.favicon, BitmapFactory.decodeByteArray(favicon, 0, favicon.length, options)); } else { views.setImageViewResource(R.id.favicon, org.chromium.chrome.R.drawable.globe_favicon); } byte[] thumbnail = bookmark.thumbnail(); if (thumbnail != null && thumbnail.length > 0) { views.setImageViewBitmap( R.id.thumb, BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length, options)); } else { views.setImageViewResource(R.id.thumb, R.drawable.browser_thumbnail); } } Intent fillIn; if (!bookmark.isUrl()) { fillIn = new Intent(getChangeFolderAction(mContext)) .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mWidgetId) .putExtra(BookmarkColumns._ID, id); } else { fillIn = new Intent(Intent.ACTION_VIEW); if (!TextUtils.isEmpty(url)) { fillIn = fillIn.addCategory(Intent.CATEGORY_BROWSABLE).setData(Uri.parse(url)); } else { fillIn = fillIn.addCategory(Intent.CATEGORY_LAUNCHER); } } views.setOnClickFillInIntent(R.id.list_item, fillIn); return views; }
@Override public int getCount() { if (mCurrentFolder == null) return 0; return mCurrentFolder.children().size() + (mCurrentFolder.parent() != null ? 1 : 0); }
private static boolean isSameHierarchy(BookmarkNode h1, BookmarkNode h2) { return isSameHierarchyDownwards(h1.getHierarchyRoot(), h2.getHierarchyRoot()); }