[iOS] Handle BookmarkActivity Within SharingCoordinator
SharingCoordinator will now handle add/edit bookmark commands sent from
the Bookmark Activity, and will make use of the new
BookmarkEditCoordiator to handle showing the Edit Bookmark UI.
(cherry picked from commit b63c5ef2d6e01126b3fe93decf9f0978fb469045)
Bug: 1133294
Change-Id: I7f69f241b49646ffb1853a4a78322f5b941b6cef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2441957
Commit-Queue: Sebastien Lalancette <[email protected]>
Reviewed-by: Gauthier Ambard <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#813754}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2458879
Reviewed-by: Sebastien Lalancette <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#110}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h
index 759729d6..187037d 100644
--- a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h
+++ b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h
@@ -11,20 +11,21 @@
class BookmarkModel;
}
-@protocol BrowserCommands;
+@protocol BookmarksCommands;
class GURL;
class PrefService;
// Activity that adds the page to bookmarks.
@interface BookmarkActivity : UIActivity
-// Initializes the bookmark activity with the |URL| to check to know if the page
-// is already bookmarked in the |bookmarkModel|. The |handler| is used to add
-// the page to the bookmarks. The |prefService| is used to verify if the user
-// can edit their bookmarks or not.
+// Initializes the bookmark activity with a page's |URL| and |title|. The
+// |bookmarkModel| to verify if the page has already been bookmarked or not. The
+// |handler| is used to add the page to the bookmarks. The |prefService| is used
+// to verify if the user can edit their bookmarks or not.
- (instancetype)initWithURL:(const GURL&)URL
+ title:(NSString*)title
bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
- handler:(id<BrowserCommands>)handler
+ handler:(id<BookmarksCommands>)handler
prefService:(PrefService*)prefService;
- (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
index bc88ae2..5cdc4f7 100644
--- a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
+++ b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
@@ -4,16 +4,18 @@
#import "ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/common/bookmark_pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "ios/chrome/browser/policy/policy_features.h"
-#include "ios/chrome/browser/ui/commands/browser_commands.h"
-#include "ios/chrome/grit/ios_strings.h"
-#include "ui/base/l10n/l10n_util_mac.h"
-#include "url/gurl.h"
+#import "base/metrics/user_metrics.h"
+#import "base/metrics/user_metrics_action.h"
+#import "components/bookmarks/browser/bookmark_model.h"
+#import "components/bookmarks/common/bookmark_pref_names.h"
+#import "components/prefs/pref_service.h"
+#import "ios/chrome/browser/policy/policy_features.h"
+#import "ios/chrome/browser/ui/commands/bookmark_page_command.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
+#import "ios/chrome/browser/ui/commands/browser_commands.h"
+#import "ios/chrome/grit/ios_strings.h"
+#import "ui/base/l10n/l10n_util_mac.h"
+#import "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
@@ -30,10 +32,12 @@
@property(nonatomic, assign) BOOL bookmarked;
// The bookmark model used to validate if a page was bookmarked.
@property(nonatomic, assign) bookmarks::BookmarkModel* bookmarkModel;
-// The URL for the activity.
+// The URL of the page to be bookmarked.
@property(nonatomic, assign) GURL URL;
+// The title of the page to be bookmarked.
+@property(nonatomic, assign) NSString* title;
// The handler invoked when the activity is performed.
-@property(nonatomic, weak) id<BrowserCommands> handler;
+@property(nonatomic, weak) id<BookmarksCommands> handler;
// User's preferences service.
@property(nonatomic, assign) PrefService* prefService;
@end
@@ -41,12 +45,14 @@
@implementation BookmarkActivity
- (instancetype)initWithURL:(const GURL&)URL
+ title:(NSString*)title
bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
- handler:(id<BrowserCommands>)handler
+ handler:(id<BookmarksCommands>)handler
prefService:(PrefService*)prefService {
self = [super init];
if (self) {
_URL = URL;
+ _title = title;
_bookmarkModel = bookmarkModel;
_handler = handler;
_prefService = prefService;
@@ -89,7 +95,9 @@
}
- (void)performActivity {
- [self.handler bookmarkCurrentPage];
+ BookmarkPageCommand* command =
+ [[BookmarkPageCommand alloc] initWithURL:self.URL title:self.title];
+ [self.handler bookmarkPage:command];
[self activityDidFinish:YES];
}
diff --git a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
index b2c59b7..3915f201 100644
--- a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
+++ b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
@@ -12,7 +12,8 @@
#include "components/prefs/testing_pref_service.h"
#include "ios/chrome/browser/policy/policy_features.h"
#include "ios/chrome/browser/ui/bookmarks/bookmark_ios_unittest.h"
-#include "ios/chrome/browser/ui/commands/browser_commands.h"
+#include "ios/chrome/browser/ui/commands/bookmark_page_command.h"
+#include "ios/chrome/browser/ui/commands/bookmarks_commands.h"
#include "ios/chrome/grit/ios_strings.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "ui/base/l10n/l10n_util_mac.h"
@@ -22,6 +23,12 @@
#error "This file requires ARC support."
#endif
+namespace {
+
+NSString* const kTestTitle = @"Test Title";
+
+} // namespace
+
// Test fixture for covering the BookmarkActivity class.
class BookmarkActivityTest : public BookmarkIOSUnitTest {
protected:
@@ -33,7 +40,7 @@
// Turn off flag by default.
scoped_features_.InitAndDisableFeature(kEditBookmarksIOS);
- mocked_handler_ = OCMProtocolMock(@protocol(BrowserCommands));
+ mocked_handler_ = OCMProtocolMock(@protocol(BookmarksCommands));
RegisterPrefs();
}
@@ -53,6 +60,7 @@
// Creates a BookmarkActivity instance with the given |URL|.
BookmarkActivity* CreateActivity(const GURL& URL) {
return [[BookmarkActivity alloc] initWithURL:URL
+ title:kTestTitle
bookmarkModel:bookmark_model_
handler:mocked_handler_
prefService:&testing_pref_service_];
@@ -97,6 +105,7 @@
TEST_F(BookmarkActivityTest, NilBookmarkModel_NoCrash) {
BookmarkActivity* activity =
[[BookmarkActivity alloc] initWithURL:GURL("https://example.com/")
+ title:kTestTitle
bookmarkModel:nil
handler:mocked_handler_
prefService:&testing_pref_service_];
@@ -127,3 +136,23 @@
l10n_util::GetNSString(IDS_IOS_TOOLS_MENU_EDIT_BOOKMARK);
EXPECT_TRUE([editBookmarkString isEqualToString:activity.activityTitle]);
}
+
+TEST_F(BookmarkActivityTest, PerformActivity_BookmarkPageCommand) {
+ GURL testUrl("https://example.com/");
+ BookmarkActivity* activity = CreateActivity(testUrl);
+
+ [[mocked_handler_ expect]
+ bookmarkPage:[OCMArg checkWithBlock:^BOOL(BookmarkPageCommand* value) {
+ EXPECT_EQ(testUrl, value.URL);
+ EXPECT_EQ(kTestTitle, value.title);
+ return YES;
+ }]];
+
+ id activity_partial_mock = OCMPartialMock(activity);
+ [[activity_partial_mock expect] activityDidFinish:YES];
+
+ [activity performActivity];
+
+ [mocked_handler_ verify];
+ [activity_partial_mock verify];
+}
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_coordinator.h b/ios/chrome/browser/ui/activity_services/activity_service_coordinator.h
index 052e92a..455d61b 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_coordinator.h
+++ b/ios/chrome/browser/ui/activity_services/activity_service_coordinator.h
@@ -11,6 +11,7 @@
@class ActivityParams;
@protocol ActivityServicePositioner;
@protocol ActivityServicePresentation;
+@protocol BookmarksCommands;
class Browser;
@protocol QRGenerationCommands;
@@ -38,7 +39,9 @@
presentationProvider;
// Handler for activities that need to be executed within a certain scope.
-@property(nonatomic, readwrite, weak) id<QRGenerationCommands> scopedHandler;
+@property(nonatomic, readwrite, weak)
+ id<BookmarksCommands, QRGenerationCommands>
+ scopedHandler;
@end
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_coordinator.mm b/ios/chrome/browser/ui/activity_services/activity_service_coordinator.mm
index 2744c3a..a74d857 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_coordinator.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_coordinator.mm
@@ -21,6 +21,7 @@
#import "ios/chrome/browser/ui/activity_services/data/share_to_data_builder.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
@@ -78,6 +79,7 @@
ios::BookmarkModelFactory::GetForBrowserState(browserState);
self.mediator =
[[ActivityServiceMediator alloc] initWithHandler:self.handler
+ bookmarksHandler:self.scopedHandler
qrGenerationHandler:self.scopedHandler
prefService:browserState->GetPrefs()
bookmarkModel:bookmarkModel];
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_mediator.h b/ios/chrome/browser/ui/activity_services/activity_service_mediator.h
index 8d9af44..9927dee4b 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_mediator.h
+++ b/ios/chrome/browser/ui/activity_services/activity_service_mediator.h
@@ -14,6 +14,7 @@
class BookmarkModel;
}
+@protocol BookmarksCommands;
@protocol BrowserCommands;
@class ChromeActivityImageSource;
@protocol ChromeActivityItemSource;
@@ -28,10 +29,12 @@
@interface ActivityServiceMediator : NSObject
// Initializes a mediator instance with a |handler| used to execute action, a
+// |bookmarksHandler| to execute Bookmarks actions, a
// |qrGenerationHandler| to execute QR generation actions, a |prefService| to
// read settings and policies, and a |bookmarkModel| to retrieve bookmark
// states.
- (instancetype)initWithHandler:(id<BrowserCommands, FindInPageCommands>)handler
+ bookmarksHandler:(id<BookmarksCommands>)bookmarksHandler
qrGenerationHandler:(id<QRGenerationCommands>)qrGenerationHandler
prefService:(PrefService*)prefService
bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_mediator.mm b/ios/chrome/browser/ui/activity_services/activity_service_mediator.mm
index 74ea239c..18be086 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_mediator.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_mediator.mm
@@ -31,6 +31,7 @@
#import "ios/chrome/browser/ui/activity_services/data/share_image_data.h"
#import "ios/chrome/browser/ui/activity_services/data/share_to_data.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
#import "ios/chrome/browser/ui/commands/qr_generation_commands.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
@@ -42,6 +43,8 @@
@property(nonatomic, weak) id<BrowserCommands, FindInPageCommands> handler;
+@property(nonatomic, weak) id<BookmarksCommands> bookmarksHandler;
+
@property(nonatomic, weak) id<QRGenerationCommands> qrGenerationHandler;
@property(nonatomic, assign) PrefService* prefService;
@@ -55,11 +58,13 @@
#pragma mark - Public
- (instancetype)initWithHandler:(id<BrowserCommands, FindInPageCommands>)handler
+ bookmarksHandler:(id<BookmarksCommands>)bookmarksHandler
qrGenerationHandler:(id<QRGenerationCommands>)qrGenerationHandler
prefService:(PrefService*)prefService
bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel {
if (self = [super init]) {
_handler = handler;
+ _bookmarksHandler = bookmarksHandler;
_qrGenerationHandler = qrGenerationHandler;
_prefService = prefService;
_bookmarkModel = bookmarkModel;
@@ -96,8 +101,9 @@
BookmarkActivity* bookmarkActivity =
[[BookmarkActivity alloc] initWithURL:data.visibleURL
+ title:data.title
bookmarkModel:self.bookmarkModel
- handler:self.handler
+ handler:self.bookmarksHandler
prefService:self.prefService];
[applicationActivities addObject:bookmarkActivity];
diff --git a/ios/chrome/browser/ui/activity_services/activity_service_mediator_unittest.mm b/ios/chrome/browser/ui/activity_services/activity_service_mediator_unittest.mm
index 466c551..e95c1c0 100644
--- a/ios/chrome/browser/ui/activity_services/activity_service_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/activity_services/activity_service_mediator_unittest.mm
@@ -25,6 +25,7 @@
#import "ios/chrome/browser/ui/activity_services/data/chrome_activity_url_source.h"
#import "ios/chrome/browser/ui/activity_services/data/share_image_data.h"
#import "ios/chrome/browser/ui/activity_services/data/share_to_data.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/find_in_page_commands.h"
#import "ios/chrome/browser/ui/commands/qr_generation_commands.h"
@@ -48,6 +49,8 @@
pref_service_ = std::make_unique<TestingPrefServiceSimple>();
mocked_handler_ = OCMStrictProtocolMock(@protocol(HandlerProtocols));
+ mocked_bookmarks_handler_ =
+ OCMStrictProtocolMock(@protocol(BookmarksCommands));
mocked_qr_generation_handler_ =
OCMStrictProtocolMock(@protocol(QRGenerationCommands));
mocked_thumbnail_generator_ =
@@ -55,6 +58,7 @@
mediator_ = [[ActivityServiceMediator alloc]
initWithHandler:mocked_handler_
+ bookmarksHandler:mocked_bookmarks_handler_
qrGenerationHandler:mocked_qr_generation_handler_
prefService:pref_service_.get()
bookmarkModel:nil];
@@ -71,6 +75,7 @@
}
id mocked_handler_;
+ id mocked_bookmarks_handler_;
id mocked_qr_generation_handler_;
id mocked_thumbnail_generator_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
diff --git a/ios/chrome/browser/ui/sharing/BUILD.gn b/ios/chrome/browser/ui/sharing/BUILD.gn
index 2c23fdf..89d56be 100644
--- a/ios/chrome/browser/ui/sharing/BUILD.gn
+++ b/ios/chrome/browser/ui/sharing/BUILD.gn
@@ -10,11 +10,17 @@
]
deps = [
"//base",
+ "//components/bookmarks/browser",
+ "//ios/chrome/browser/bookmarks",
+ "//ios/chrome/browser/main:public",
"//ios/chrome/browser/ui/activity_services",
"//ios/chrome/browser/ui/activity_services/requirements",
+ "//ios/chrome/browser/ui/bookmarks:core",
+ "//ios/chrome/browser/ui/bookmarks:edit",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
"//ios/chrome/browser/ui/qr_generator",
+ "//ios/third_party/material_components_ios",
"//url",
]
}
@@ -27,13 +33,21 @@
":sharing",
"//base",
"//base/test:test_support",
+ "//components/bookmarks/browser",
+ "//components/bookmarks/test",
+ "//ios/chrome/browser/bookmarks",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main:test_support",
"//ios/chrome/browser/ui/activity_services",
"//ios/chrome/browser/ui/activity_services/requirements",
+ "//ios/chrome/browser/ui/bookmarks:bookmarks_ui",
+ "//ios/chrome/browser/ui/bookmarks:edit",
+ "//ios/chrome/browser/ui/bookmarks:test_support",
"//ios/chrome/browser/ui/commands",
+ "//ios/chrome/browser/ui/table_view",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/test:test_support",
+ "//ios/third_party/material_components_ios",
"//ios/web/public",
"//ios/web/public/test",
"//ios/web/public/test/fakes",
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator.mm
index 39b4cbf..dd08070c 100644
--- a/ios/chrome/browser/ui/sharing/sharing_coordinator.mm
+++ b/ios/chrome/browser/ui/sharing/sharing_coordinator.mm
@@ -4,24 +4,42 @@
#import "ios/chrome/browser/ui/sharing/sharing_coordinator.h"
+#import <MaterialComponents/MaterialSnackbar.h>
+
+#import "base/ios/block_types.h"
+#import "components/bookmarks/browser/bookmark_model.h"
+#import "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/ui/activity_services/activity_params.h"
#import "ios/chrome/browser/ui/activity_services/activity_service_coordinator.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
+#import "ios/chrome/browser/ui/bookmarks/bookmark_edit_coordinator.h"
+#import "ios/chrome/browser/ui/bookmarks/bookmark_mediator.h"
+#import "ios/chrome/browser/ui/commands/bookmark_page_command.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
+#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/qr_generation_commands.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
#import "ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h"
-#include "url/gurl.h"
+#import "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
+using bookmarks::BookmarkNode;
+
@interface SharingCoordinator () <ActivityServicePositioner,
ActivityServicePresentation,
+ BookmarkEditCoordinatorDelegate,
+ BookmarksCommands,
QRGenerationCommands>
@property(nonatomic, strong)
ActivityServiceCoordinator* activityServiceCoordinator;
+@property(nonatomic, strong) BookmarkEditCoordinator* bookmarkEditCoordinator;
+
@property(nonatomic, strong) QRGeneratorCoordinator* qrGeneratorCoordinator;
@property(nonatomic, strong) ActivityParams* params;
@@ -62,6 +80,7 @@
- (void)stop {
[self activityServiceDidEndPresenting];
+ [self bookmarkEditDismissed:self.bookmarkEditCoordinator];
[self hideQRCode];
self.originView = nil;
}
@@ -79,6 +98,61 @@
self.activityServiceCoordinator = nil;
}
+#pragma mark - BookmarksCommands
+
+- (void)bookmarkPage:(BookmarkPageCommand*)command {
+ DCHECK(command);
+ DCHECK(command.URL.is_valid());
+
+ ChromeBrowserState* browserState = self.browser->GetBrowserState();
+ bookmarks::BookmarkModel* bookmarkModel =
+ ios::BookmarkModelFactory::GetForBrowserState(browserState);
+ if (!bookmarkModel && bookmarkModel->loaded()) {
+ return;
+ }
+
+ const BookmarkNode* node =
+ bookmarkModel->GetMostRecentlyAddedUserNodeForURL(command.URL);
+ if (node) {
+ // Trigger the Edit bookmark scenario.
+ [self editBookmark:node];
+ } else {
+ // Add the bookmark and show a snackbar message.
+ id<SnackbarCommands> handler = HandlerForProtocol(
+ self.browser->GetCommandDispatcher(), SnackbarCommands);
+ BookmarkMediator* mediator = [[BookmarkMediator alloc]
+ initWithBrowserState:self.browser->GetBrowserState()];
+
+ __weak __typeof(self) weakSelf = self;
+ ProceduralBlock editAction = ^{
+ if (!weakSelf || !bookmarkModel) {
+ return;
+ }
+
+ const BookmarkNode* newNode =
+ bookmarkModel->GetMostRecentlyAddedUserNodeForURL(command.URL);
+ DCHECK(newNode);
+ if (newNode) {
+ [weakSelf editBookmark:newNode];
+ }
+ };
+
+ MDCSnackbarMessage* snackbarMessage =
+ [mediator addBookmarkWithTitle:command.title
+ URL:command.URL
+ editAction:editAction];
+ [handler showSnackbarMessage:snackbarMessage];
+ }
+}
+
+#pragma mark - BookmarkEditCoordinatorDelegate
+
+- (void)bookmarkEditDismissed:(BookmarkEditCoordinator*)coordinator {
+ DCHECK(self.bookmarkEditCoordinator == coordinator);
+ [self.bookmarkEditCoordinator stop];
+ self.bookmarkEditCoordinator = nil;
+}
+
#pragma mark - QRGenerationCommands
- (void)generateQRCode:(GenerateQRCodeCommand*)command {
@@ -96,4 +170,16 @@
self.qrGeneratorCoordinator = nil;
}
+#pragma mark - Private Methods
+
+- (void)editBookmark:(const BookmarkNode*)bookmark {
+ self.bookmarkEditCoordinator = [[BookmarkEditCoordinator alloc]
+ initWithBaseViewController:self.baseViewController
+ browser:self.browser
+ bookmark:bookmark];
+ self.bookmarkEditCoordinator.delegate = self;
+
+ [self.bookmarkEditCoordinator start];
+}
+
@end
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
index eaa7b00d..0abcf45 100644
--- a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
@@ -4,36 +4,53 @@
#import "ios/chrome/browser/ui/sharing/sharing_coordinator.h"
+#import <MaterialComponents/MaterialSnackbar.h>
#import <UIKit/UIKit.h>
-#include "base/values.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/main/test_browser.h"
+#import "base/ios/block_types.h"
+#import "base/strings/sys_string_conversions.h"
+#import "base/values.h"
+#import "components/bookmarks/browser/bookmark_model.h"
+#import "components/bookmarks/browser/bookmark_node.h"
+#import "components/bookmarks/test/bookmark_test_helpers.h"
+#import "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
+#import "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#import "ios/chrome/browser/main/test_browser.h"
#import "ios/chrome/browser/ui/activity_services/activity_params.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
#import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
+#import "ios/chrome/browser/ui/bookmarks/bookmark_edit_coordinator.h"
+#import "ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.h"
+#import "ios/chrome/browser/ui/bookmarks/bookmark_ios_unittest.h"
+#import "ios/chrome/browser/ui/commands/bookmark_page_command.h"
+#import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/commands/generate_qr_code_command.h"
#import "ios/chrome/browser/ui/commands/qr_generation_commands.h"
+#import "ios/chrome/browser/ui/commands/snackbar_commands.h"
+#import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/chrome/test/scoped_key_window.h"
#import "ios/web/public/test/fakes/test_navigation_manager.h"
#import "ios/web/public/test/fakes/test_web_state.h"
-#include "ios/web/public/test/web_task_environment.h"
+#import "ios/web/public/test/web_task_environment.h"
#import "ios/web/public/web_state.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gtest_mac.h"
-#include "testing/platform_test.h"
+#import "testing/gmock/include/gmock/gmock.h"
+#import "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#import "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
-#include "third_party/ocmock/gtest_support.h"
-#include "url/gurl.h"
+#import "third_party/ocmock/gtest_support.h"
+#import "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
+using bookmarks::BookmarkModel;
+using bookmarks::BookmarkNode;
+
class MockTestWebState : public web::TestWebState {
public:
MockTestWebState() : web::TestWebState() {
@@ -45,27 +62,72 @@
};
// Test fixture for testing SharingCoordinator.
-class SharingCoordinatorTest : public PlatformTest {
+class SharingCoordinatorTest : public BookmarkIOSUnitTest {
protected:
SharingCoordinatorTest()
: base_view_controller_([[UIViewController alloc] init]),
- browser_(std::make_unique<TestBrowser>()),
fake_origin_view_([[UIView alloc] init]),
test_scenario_(ActivityScenario::TabShareButton) {
[scoped_key_window_.Get() setRootViewController:base_view_controller_];
}
+ void SetUp() override {
+ BookmarkIOSUnitTest::SetUp();
+ snackbar_handler_ = OCMStrictProtocolMock(@protocol(SnackbarCommands));
+ [browser_->GetCommandDispatcher()
+ startDispatchingToTarget:snackbar_handler_
+ forProtocol:@protocol(SnackbarCommands)];
+ }
+
void AppendNewWebState(std::unique_ptr<web::TestWebState> web_state) {
browser_->GetWebStateList()->InsertWebState(
WebStateList::kInvalidIndex, std::move(web_state),
WebStateList::INSERT_ACTIVATE, WebStateOpener());
}
- web::WebTaskEnvironment task_environment_;
+ // Validates that |trigger_block| gets a Edit Bookmark VC to be presented,
+ // and that |delegate| controls its dismissal.
+ void ValidateEditBookmark(ProceduralBlock trigger_block,
+ id<BookmarkEditCoordinatorDelegate> delegate) {
+ id vc_partial_mock = OCMPartialMock(base_view_controller_);
+ __block BookmarkEditViewController* bookmarkEditVC;
+ [[vc_partial_mock expect]
+ presentViewController:[OCMArg checkWithBlock:^BOOL(
+ UIViewController* viewController) {
+ if ([viewController
+ isKindOfClass:[TableViewNavigationController class]]) {
+ TableViewNavigationController* navController =
+ (TableViewNavigationController*)viewController;
+ if ([navController.tableViewController
+ isKindOfClass:[BookmarkEditViewController class]]) {
+ bookmarkEditVC = (BookmarkEditViewController*)
+ navController.tableViewController;
+ return YES;
+ }
+ return NO;
+ }
+ return NO;
+ }]
+ animated:YES
+ completion:nil];
+
+ trigger_block();
+
+ [vc_partial_mock verify];
+
+ [[vc_partial_mock expect] dismissViewControllerAnimated:YES completion:nil];
+
+ // Dismiss the ViewController.
+ ASSERT_NE(nil, bookmarkEditVC);
+ [bookmarkEditVC dismiss];
+
+ [vc_partial_mock verify];
+ }
+
ScopedKeyWindow scoped_key_window_;
UIViewController* base_view_controller_;
- std::unique_ptr<TestBrowser> browser_;
UIView* fake_origin_view_;
+ id snackbar_handler_;
ActivityScenario test_scenario_;
};
@@ -196,3 +258,87 @@
[vc_partial_mock verify];
}
+
+// Tests that the coordinator can handle adding a new bookmark, and the edit
+// action is hooked-up properly.
+TEST_F(SharingCoordinatorTest, AddBookmark_EditViaSnackbar) {
+ @autoreleasepool {
+ ActivityParams* params =
+ [[ActivityParams alloc] initWithScenario:test_scenario_];
+ SharingCoordinator* coordinator = [[SharingCoordinator alloc]
+ initWithBaseViewController:base_view_controller_
+ browser:browser_.get()
+ params:params
+ originView:fake_origin_view_];
+
+ __block ProceduralBlock edit_action = nil;
+ [[snackbar_handler_ expect]
+ showSnackbarMessage:[OCMArg checkWithBlock:^BOOL(
+ MDCSnackbarMessage* message) {
+ edit_action = message.action.handler;
+ return YES;
+ }]];
+
+ GURL test_url("https://wwww.chromium.org");
+ NSString* test_title = @"Test Title";
+ BookmarkPageCommand* command =
+ [[BookmarkPageCommand alloc] initWithURL:test_url title:test_title];
+
+ ASSERT_EQ(nil,
+ bookmark_model_->GetMostRecentlyAddedUserNodeForURL(command.URL));
+
+ auto handler = static_cast<id<BookmarksCommands>>(coordinator);
+ [handler bookmarkPage:command];
+
+ const BookmarkNode* bookmark =
+ bookmark_model_->GetMostRecentlyAddedUserNodeForURL(command.URL);
+
+ ASSERT_NE(nil, bookmark);
+ EXPECT_EQ(test_url, bookmark->url());
+ EXPECT_EQ(base::SysNSStringToUTF16(test_title), bookmark->GetTitle());
+
+ [snackbar_handler_ verify];
+ ASSERT_NE(nil, edit_action);
+
+ // Verify snackbar message's Edit action.
+ auto bookmark_delegate =
+ static_cast<id<BookmarkEditCoordinatorDelegate>>(coordinator);
+
+ ValidateEditBookmark(edit_action, bookmark_delegate);
+ }
+}
+
+// Tests that the coordinator can handle editing an existing bookmark via the
+// bookmarkPage command.
+TEST_F(SharingCoordinatorTest, EditExistingBookmark) {
+ @autoreleasepool {
+ ActivityParams* params =
+ [[ActivityParams alloc] initWithScenario:test_scenario_];
+ SharingCoordinator* coordinator = [[SharingCoordinator alloc]
+ initWithBaseViewController:base_view_controller_
+ browser:browser_.get()
+ params:params
+ originView:fake_origin_view_];
+
+ const BookmarkNode* bookmark =
+ AddBookmark(bookmark_model_->mobile_node(), @"Some Other Title");
+
+ NSString* test_title = @"Test Title";
+ BookmarkPageCommand* command =
+ [[BookmarkPageCommand alloc] initWithURL:bookmark->url()
+ title:test_title];
+
+ ASSERT_EQ(bookmark,
+ bookmark_model_->GetMostRecentlyAddedUserNodeForURL(command.URL));
+
+ auto handler = static_cast<id<BookmarksCommands>>(coordinator);
+
+ ProceduralBlock trigger = ^{
+ [handler bookmarkPage:command];
+ };
+ auto bookmark_delegate =
+ static_cast<id<BookmarkEditCoordinatorDelegate>>(coordinator);
+
+ ValidateEditBookmark(trigger, bookmark_delegate);
+ }
+}