Skip to content

Commit

Permalink
Add copy clean link to the macOS application menu bar
Browse files Browse the repository at this point in the history
  • Loading branch information
spylogsster committed Dec 7, 2022
1 parent 7d527cc commit 4bffcdd
Show file tree
Hide file tree
Showing 16 changed files with 254 additions and 8 deletions.
25 changes: 25 additions & 0 deletions browser/brave_app_controller_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_BRAVE_APP_CONTROLLER_MAC_H_
#define BRAVE_BROWSER_BRAVE_APP_CONTROLLER_MAC_H_

#import "chrome/browser/app_controller_mac.h"

// Manages logic to switch hotkey between copy and copy clean link item.
@interface BraveAppController : AppController {
NSMenuItem* _copyMenuItem;
NSMenuItem* _copyCleanLinkMenuItem;
absl::optional<bool> _hasSelectedURLForTesting;
}

// Testing API.
- (void)setCopyMenuItemForTesting:(NSMenuItem*)menuItem;
- (void)setCopyCleanLinkMenuItemForTesting:(NSMenuItem*)menuItem;
- (void)setSelectedURLForTesting:(bool)selected;

@end

#endif // BRAVE_BROWSER_BRAVE_APP_CONTROLLER_MAC_H_
103 changes: 103 additions & 0 deletions browser/brave_app_controller_mac.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#import "brave/browser/brave_app_controller_mac.h"

#include "brave/app/brave_command_ids.h"
#include "brave/browser/ui/browser_commands.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/grit/generated_resources.h"

@implementation BraveAppController

- (void)mainMenuCreated {
[super mainMenuCreated];

NSMenu* editMenu = [[[NSApp mainMenu] itemWithTag:IDC_EDIT_MENU] submenu];
_copyMenuItem = [editMenu itemWithTag:IDC_CONTENT_CONTEXT_COPY];
DCHECK(_copyMenuItem);
[[_copyMenuItem menu] setDelegate:self];
_copyCleanLinkMenuItem = [editMenu itemWithTag:IDC_COPY_CLEAN_LINK];
DCHECK(_copyCleanLinkMenuItem);
[[_copyCleanLinkMenuItem menu] setDelegate:self];
}

- (void)dealloc {
[[_copyMenuItem menu] setDelegate:nil];
[[_copyCleanLinkMenuItem menu] setDelegate:nil];
[super dealloc];
}

- (Browser*)getBrowser {
return chrome::FindBrowserWithProfile([self lastProfileIfLoaded]);
}

- (BOOL)shouldShowCleanLinkItem {
if (_hasSelectedURLForTesting.has_value()) {
return _hasSelectedURLForTesting.value();
}
return brave::HasSelectedURL([self getBrowser]);
}

- (void)setKeyEquivalentToItem:(NSMenuItem*)item {
auto* hootkeyItem =
item == _copyMenuItem ? _copyMenuItem : _copyCleanLinkMenuItem;
auto* noHootkeyItem =
item == _copyMenuItem ? _copyCleanLinkMenuItem : _copyMenuItem;

[hootkeyItem setKeyEquivalent:@"c"];
[hootkeyItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand];

[noHootkeyItem setKeyEquivalent:@""];
[noHootkeyItem setKeyEquivalentModifierMask:0];
}

- (void)menuNeedsUpdate:(NSMenu*)menu {
if (menu != [_copyMenuItem menu] && menu != [_copyCleanLinkMenuItem menu]) {
[super menuNeedsUpdate:menu];
return;
}
if ([self shouldShowCleanLinkItem]) {
[_copyCleanLinkMenuItem setHidden:NO];
[self setKeyEquivalentToItem:_copyCleanLinkMenuItem];
} else {
[_copyCleanLinkMenuItem setHidden:YES];
[self setKeyEquivalentToItem:_copyMenuItem];
}
}

- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
NSInteger tag = [item tag];
if (tag == IDC_COPY_CLEAN_LINK) {
return [self shouldShowCleanLinkItem];
}
return [super validateUserInterfaceItem:item];
}

- (void)commandDispatch:(id)sender {
NSInteger tag = [sender tag];
if (tag == IDC_COPY_CLEAN_LINK) {
chrome::ExecuteCommand([self getBrowser], IDC_COPY_CLEAN_LINK);
return;
}

[super commandDispatch:sender];
}

- (void)setCopyMenuItemForTesting:(NSMenuItem*)menuItem {
_copyMenuItem = menuItem;
}

- (void)setCopyCleanLinkMenuItemForTesting:(NSMenuItem*)menuItem {
_copyCleanLinkMenuItem = menuItem;
}
- (void)setSelectedURLForTesting:(bool)value {
_hasSelectedURLForTesting = value;
}

@end // @implementation BraveAppController
77 changes: 77 additions & 0 deletions browser/brave_app_controller_mac_unittest.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#import <Cocoa/Cocoa.h>

#import "brave/browser/brave_app_controller_mac.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/platform_test.h"

class BraveAppControllerTest : public PlatformTest {
protected:
BraveAppControllerTest() {}

void SetUp() override {
PlatformTest::SetUp();
braveAppController_.reset([[BraveAppController alloc] init]);
copyMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@""
action:0
keyEquivalent:@""]);
[braveAppController_ setCopyMenuItemForTesting:copyMenuItem_];

copyCleanLinkMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@""
action:0
keyEquivalent:@""]);
[braveAppController_
setCopyCleanLinkMenuItemForTesting:copyCleanLinkMenuItem_];
}

void TearDown() override {
[braveAppController_ setCopyMenuItemForTesting:nil];
[braveAppController_ setCopyCleanLinkMenuItemForTesting:nil];
PlatformTest::TearDown();
}

void CheckHotkeysOnCopyItem() {
[braveAppController_ setSelectedURLForTesting:false];

[braveAppController_ menuNeedsUpdate:[copyMenuItem_ menu]];

EXPECT_TRUE([[copyMenuItem_ keyEquivalent] isEqualToString:@"c"]);
EXPECT_EQ([copyMenuItem_ keyEquivalentModifierMask],
NSEventModifierFlagCommand);

EXPECT_TRUE([[copyCleanLinkMenuItem_ keyEquivalent] isEqualToString:@""]);
EXPECT_EQ([copyCleanLinkMenuItem_ keyEquivalentModifierMask], 0UL);
EXPECT_TRUE([copyCleanLinkMenuItem_ isHidden]);
}

void CheckHotkeysOnCleanLinkItem() {
[braveAppController_ setSelectedURLForTesting:true];

[braveAppController_ menuNeedsUpdate:[copyMenuItem_ menu]];

EXPECT_TRUE([[copyMenuItem_ keyEquivalent] isEqualToString:@""]);
EXPECT_EQ([copyMenuItem_ keyEquivalentModifierMask], 0UL);

EXPECT_TRUE([[copyCleanLinkMenuItem_ keyEquivalent] isEqualToString:@"c"]);
EXPECT_EQ([copyCleanLinkMenuItem_ keyEquivalentModifierMask],
NSEventModifierFlagCommand);
EXPECT_FALSE([copyCleanLinkMenuItem_ isHidden]);
}

base::scoped_nsobject<BraveAppController> braveAppController_;
base::scoped_nsobject<NSMenuItem> copyMenuItem_;
base::scoped_nsobject<NSMenuItem> copyCleanLinkMenuItem_;
content::BrowserTaskEnvironment task_environment_;
};

TEST_F(BraveAppControllerTest, OnlyCopyItem) {
CheckHotkeysOnCopyItem();
}

TEST_F(BraveAppControllerTest, CleanLinkItemAdded) {
CheckHotkeysOnCleanLinkItem();
}
2 changes: 2 additions & 0 deletions browser/sources.gni
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,8 @@ brave_chrome_browser_deps = [

if (is_mac) {
brave_chrome_browser_sources += [
"//brave/browser/brave_app_controller_mac.h",
"//brave/browser/brave_app_controller_mac.mm",
"//brave/browser/brave_browser_main_parts_mac.h",
"//brave/browser/brave_browser_main_parts_mac.mm",
"//brave/browser/brave_shell_integration_mac.h",
Expand Down
8 changes: 8 additions & 0 deletions browser/ui/browser_commands.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,12 @@ void ToggleActiveTabAudioMute(Browser* browser) {
std::string());
}

bool HasSelectedURL(Browser* browser) {
#if defined(TOOLKIT_VIEWS)
return static_cast<BraveBrowserView*>(browser->window())->HasSelectedURL();
#else
return false;
#endif
}

} // namespace brave
2 changes: 1 addition & 1 deletion browser/ui/browser_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Browser;
class GURL;

namespace brave {

bool HasSelectedURL(Browser* browser);
void NewOffTheRecordWindowTor(Browser*);
void NewTorConnectionForSite(Browser*);
void AddNewProfile();
Expand Down
5 changes: 5 additions & 0 deletions browser/ui/views/frame/brave_browser_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "brave/browser/ui/views/frame/vertical_tab_strip_region_view.h"
#include "brave/browser/ui/views/frame/vertical_tab_strip_widget_delegate_view.h"
#include "brave/browser/ui/views/location_bar/brave_location_bar_view.h"
#include "brave/browser/ui/views/omnibox/brave_omnibox_view_views.h"
#include "brave/browser/ui/views/sidebar/sidebar_container_view.h"
#include "brave/browser/ui/views/tabs/features.h"
#include "brave/browser/ui/views/toolbar/bookmark_button.h"
Expand Down Expand Up @@ -405,6 +406,10 @@ speedreader::SpeedreaderBubbleView* BraveBrowserView::ShowSpeedreaderBubble(
#endif
}

bool BraveBrowserView::HasSelectedURL() const {
return GetLocationBarView()->omnibox_view()->SelectedTextIsURL();
}

WalletButton* BraveBrowserView::GetWalletButton() {
return static_cast<BraveToolbarView*>(toolbar())->wallet_button();
}
Expand Down
1 change: 1 addition & 0 deletions browser/ui/views/frame/brave_browser_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class BraveBrowserView : public BrowserView {

views::View* sidebar_host_view() { return sidebar_host_view_; }
bool IsSidebarVisible() const;
bool HasSelectedURL() const;

VerticalTabStripWidgetDelegateView*
vertical_tab_strip_widget_delegate_view() {
Expand Down
10 changes: 10 additions & 0 deletions chromium_src/chrome/browser/chrome_browser_main_mac.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* Copyright (c) 2022 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "chrome/browser/chrome_browser_main_mac.h"
#import "brave/browser/brave_app_controller_mac.h"

#define AppController BraveAppController
#include "src/chrome/browser/chrome_browser_main_mac.mm"
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2018 The Brave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/* Copyright (c) 2018 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */

#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"

Expand Down
13 changes: 13 additions & 0 deletions chromium_src/chrome/browser/ui/cocoa/main_menu_builder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@

#include "brave/app/brave_command_ids.h"
#include "brave/grit/brave_generated_resources.h"
#include "chrome/grit/generated_resources.h"

namespace {
constexpr int kPasteMacResourceId = IDS_PASTE_MAC;
}

#define BRAVE_BUILD_FILE_MENU \
Item(IDS_NEW_OFFTHERECORD_WINDOW_TOR) \
Expand All @@ -14,5 +19,13 @@
Item(IDS_REPORT_BROKEN_SITE_MAC) \
.command_id(IDC_SHOW_BRAVE_WEBCOMPAT_REPORTER),

#undef IDS_PASTE_MAC
#define IDS_PASTE_MAC IDS_COPY_CLEAN_LINK) \
.command_id(IDC_COPY_CLEAN_LINK) \
.target(app_delegate), \
Item(kPasteMacResourceId

#include "src/chrome/browser/ui/cocoa/main_menu_builder.mm"
#undef BRAVE_WEBCOMPAT_REPORTER_MENU_ENTRY
#undef IDS_PASTE_MAC
#define IDS_PASTE_MAC kPasteMacResourceId
2 changes: 1 addition & 1 deletion chromium_src/ui/views/controls/textfield/textfield.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "ui/views/controls/textfield/textfield.h"
#include "base/logging.h"
Expand Down
2 changes: 1 addition & 1 deletion chromium_src/ui/views/controls/textfield/textfield.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
// You can obtain one at https://mozilla.org/MPL/2.0/.

#ifndef BRAVE_CHROMIUM_SRC_UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_H_
#define BRAVE_CHROMIUM_SRC_UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_H_
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// You can obtain one at https://mozilla.org/MPL/2.0/.

#include "ui/views/controls/textfield/textfield_controller.h"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// You can obtain one at https://mozilla.org/MPL/2.0/.

#ifndef BRAVE_CHROMIUM_SRC_UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_CONTROLLER_H_
#define BRAVE_CHROMIUM_SRC_UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_CONTROLLER_H_
Expand Down
1 change: 1 addition & 0 deletions test/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ test("brave_unit_tests") {

if (is_mac) {
sources += [
"//brave/browser/brave_app_controller_mac_unittest.mm",
"//brave/chromium_src/chrome/browser/shell_integration_unittest_mac.cc",
"//brave/chromium_src/chrome/common/chrome_constants_unittest_mac.cc",
]
Expand Down

0 comments on commit 4bffcdd

Please sign in to comment.