summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-07-01 13:23:52 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-07-01 11:25:08 +0000
commit5d013f5804a0d91fcf6c626b2d6fb6eca5c845b0 (patch)
tree49758e2556cca8f7d386b49a6c41b3bcb7c20b48 /chromium/chrome/browser
parent189d4fd8fad9e3c776873be51938cd31a42b6177 (diff)
downloadqtwebengine-chromium-5d013f5804a0d91fcf6c626b2d6fb6eca5c845b0.tar.gz
BASELINE: Update Chromium to 90.0.4430.228
Change-Id: I2d24c073cefc4842980b84cc7e9c5419c107c501 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser')
-rw-r--r--chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc34
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api.cc106
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc113
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_constants.h2
-rw-r--r--chromium/chrome/browser/ui/webui/invalidations/invalidations_message_handler.cc7
7 files changed, 252 insertions, 45 deletions
diff --git a/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc b/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
index 2a624978225..a1079a10ec9 100644
--- a/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
+++ b/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api.cc
@@ -123,7 +123,10 @@ ExtensionFunction::ResponseAction TabGroupsQueryFunction::Run() {
}
}
- TabStripModel* tab_strip = browser->tab_strip_model();
+ TabStripModel* tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableQueryError));
for (const tab_groups::TabGroupId& id :
tab_strip->group_model()->ListTabGroups()) {
const tab_groups::TabGroupVisualData* visual_data =
@@ -184,8 +187,11 @@ ExtensionFunction::ResponseAction TabGroupsUpdateFunction::Run() {
if (params->update_properties.title.get())
title = base::UTF8ToUTF16(*params->update_properties.title);
- TabGroup* tab_group =
- browser->tab_strip_model()->group_model()->GetTabGroup(id);
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip_model)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+ TabGroup* tab_group = tab_strip_model->group_model()->GetTabGroup(id);
tab_groups::TabGroupVisualData new_visual_data(title, color, collapsed);
tab_group->SetVisualData(std::move(new_visual_data));
@@ -232,12 +238,12 @@ bool TabGroupsMoveFunction::MoveGroup(int group_id,
return false;
}
- if (!source_browser->window()->IsTabStripEditable()) {
+ TabStripModel* source_tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(source_browser);
+ if (!source_tab_strip) {
*error = tabs_constants::kTabStripNotEditableError;
return false;
}
-
- TabStripModel* source_tab_strip = source_browser->tab_strip_model();
gfx::Range tabs =
source_tab_strip->group_model()->GetTabGroup(*group)->ListTabs();
if (tabs.length() == 0)
@@ -252,11 +258,6 @@ bool TabGroupsMoveFunction::MoveGroup(int group_id,
return false;
}
- if (!target_browser->window()->IsTabStripEditable()) {
- *error = tabs_constants::kTabStripNotEditableError;
- return false;
- }
-
// TODO(crbug.com/990158): Rather than calling is_type_normal(), should
// this call SupportsWindowFeature(Browser::FEATURE_TABSTRIP)?
if (!target_browser->is_type_normal()) {
@@ -271,7 +272,12 @@ bool TabGroupsMoveFunction::MoveGroup(int group_id,
// If windowId is different from the current window, move between windows.
if (target_browser != source_browser) {
- TabStripModel* target_tab_strip = target_browser->tab_strip_model();
+ TabStripModel* target_tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(target_browser);
+ if (!target_tab_strip) {
+ *error = tabs_constants::kTabStripNotEditableError;
+ return false;
+ }
if (new_index > target_tab_strip->count() || new_index < 0)
new_index = target_tab_strip->count();
diff --git a/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc b/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc
index efebc9b2638..4934de996d4 100644
--- a/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/tab_groups/tab_groups_api_unittest.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/extensions/api/tab_groups/tab_groups_event_router.h"
#include "chrome/browser/extensions/api/tab_groups/tab_groups_event_router_factory.h"
#include "chrome/browser/extensions/api/tab_groups/tab_groups_util.h"
+#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/extension_tab_util.h"
@@ -124,13 +125,12 @@ void TabGroupsApiUnitTest::SetUp() {
InitializeEmptyExtensionService();
// Create a browser window.
- TestBrowserWindow* window = new TestBrowserWindow;
+ browser_window_ = std::make_unique<TestBrowserWindow>();
// TestBrowserWindowOwner handles its own lifetime, and also cleans up
// |window2|.
- new TestBrowserWindowOwner(window);
Browser::CreateParams params(profile(), /* user_gesture */ true);
params.type = Browser::TYPE_NORMAL;
- params.window = window;
+ params.window = browser_window_.get();
browser_ = std::unique_ptr<Browser>(Browser::Create(params));
BrowserList::SetLastActive(browser_.get());
@@ -545,4 +545,32 @@ TEST_F(TabGroupsApiUnitTest, TabGroupsOnMoved) {
api::tab_groups::OnMoved::kEventName));
}
+// Test that tab groups aren't edited while dragging.
+TEST_F(TabGroupsApiUnitTest, IsTabStripEditable) {
+ scoped_refptr<const Extension> extension = CreateTabGroupsExtension();
+ int group_id = tab_groups_util::GetGroupId(
+ browser()->tab_strip_model()->AddToNewGroup({0}));
+ const std::string args =
+ base::StringPrintf(R"([%d, {"index": %d}])", group_id, 1);
+
+ // Succeed moving group in normal case.
+ {
+ auto function = base::MakeRefCounted<TabGroupsMoveFunction>();
+ function->set_extension(extension);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), args, browser(), api_test_utils::NONE));
+ }
+
+ // Gracefully cancel group tab drag if tab strip isn't editable.
+ {
+ browser_window()->SetIsTabStripEditable(false);
+ auto function = base::MakeRefCounted<TabGroupsMoveFunction>();
+ function->set_extension(extension);
+ std::string error =
+ extension_function_test_utils::RunFunctionAndReturnError(
+ function.get(), args, browser());
+ EXPECT_EQ(tabs_constants::kTabStripNotEditableError, error);
+ }
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
index 6c34a459aab..ddd17b8f91f 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -308,7 +308,7 @@ int MoveTabToWindow(ExtensionFunction* function,
return -1;
}
- if (!target_browser->window()->IsTabStripEditable()) {
+ if (!ExtensionTabUtil::IsTabStripEditable()) {
*error = tabs_constants::kTabStripNotEditableError;
return -1;
}
@@ -333,7 +333,9 @@ int MoveTabToWindow(ExtensionFunction* function,
return -1;
}
- TabStripModel* target_tab_strip = target_browser->tab_strip_model();
+ TabStripModel* target_tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(target_browser);
+ DCHECK(target_tab_strip);
// Clamp move location to the last position.
// This is ">" because it can append to a new index position.
@@ -581,7 +583,7 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
return RespondNow(Error(std::move(error)));
}
- if (!source_browser->window()->IsTabStripEditable())
+ if (!ExtensionTabUtil::IsTabStripEditable())
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
if (source_browser->profile() != window_profile)
@@ -699,7 +701,10 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
std::unique_ptr<content::WebContents> detached_tab =
source_tab_strip->DetachWebContentsAt(tab_index);
contents = detached_tab.get();
- TabStripModel* target_tab_strip = new_window->tab_strip_model();
+ TabStripModel* target_tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(new_window);
+ if (!target_tab_strip)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
target_tab_strip->InsertWebContentsAt(
urls.size(), std::move(detached_tab), TabStripModel::ADD_NONE);
}
@@ -926,7 +931,10 @@ ExtensionFunction::ResponseAction TabsGetSelectedFunction::Run() {
if (!GetBrowserFromWindowID(this, window_id, &browser, &error))
return RespondNow(Error(std::move(error)));
- TabStripModel* tab_strip = browser->tab_strip_model();
+ TabStripModel* tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
WebContents* contents = tab_strip->GetActiveWebContents();
if (!contents)
return RespondNow(Error(tabs_constants::kNoSelectedTabError));
@@ -1044,6 +1052,7 @@ ExtensionFunction::ResponseAction TabsQueryFunction::Run() {
}
TabStripModel* tab_strip = browser->tab_strip_model();
+ DCHECK(tab_strip);
for (int i = 0; i < tab_strip->count(); ++i) {
WebContents* web_contents = tab_strip->GetWebContentsAt(i);
@@ -1193,6 +1202,9 @@ ExtensionFunction::ResponseAction TabsDuplicateFunction::Run() {
return RespondNow(Error(std::move(error)));
}
+ if (!ExtensionTabUtil::IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
WebContents* new_contents = chrome::DuplicateTabAt(browser, tab_index);
if (!has_callback())
return RespondNow(NoArguments());
@@ -1261,7 +1273,10 @@ ExtensionFunction::ResponseAction TabsHighlightFunction::Run() {
if (!GetBrowserFromWindowID(this, window_id, &browser, &error))
return RespondNow(Error(std::move(error)));
- TabStripModel* tabstrip = browser->tab_strip_model();
+ // Don't let the extension update the tab if the user is dragging tabs.
+ TabStripModel* tabstrip = ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tabstrip)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
ui::ListSelectionModel selection;
int active_index = -1;
@@ -1287,7 +1302,11 @@ ExtensionFunction::ResponseAction TabsHighlightFunction::Run() {
return RespondNow(Error(tabs_constants::kNoHighlightedTabError));
selection.set_active(active_index);
- browser->tab_strip_model()->SetSelectionFromModel(std::move(selection));
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip_model)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+ tab_strip_model->SetSelectionFromModel(std::move(selection));
return RespondNow(OneArgument(base::Value::FromUniquePtrValue(
ExtensionTabUtil::CreateWindowValueForExtension(
*browser, extension(), ExtensionTabUtil::kPopulateTabs,
@@ -1299,13 +1318,6 @@ bool TabsHighlightFunction::HighlightTab(TabStripModel* tabstrip,
int* active_index,
int index,
std::string* error) {
- // Cannot change tab highlight. This may for instance be due to user dragging
- // in progress.
- if (!tabstrip->delegate()->CanHighlightTabs()) {
- *error = tabs_constants::kCannotHighlightTabs;
- return false;
- }
-
// Make sure the index is in range.
if (!tabstrip->ContainsIndex(index)) {
*error = ErrorUtils::FormatErrorMessage(
@@ -1334,7 +1346,11 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
Browser* browser = ChromeExtensionFunctionDetails(this).GetCurrentBrowser();
if (!browser)
return RespondNow(Error(tabs_constants::kNoCurrentWindowError));
- contents = browser->tab_strip_model()->GetActiveWebContents();
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip_model)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+ contents = tab_strip_model->GetActiveWebContents();
if (!contents)
return RespondNow(Error(tabs_constants::kNoSelectedTabError));
tab_id = sessions::SessionTabHelper::IdForTab(contents).id();
@@ -1383,6 +1399,11 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
active = *params->update_properties.active;
if (active) {
+ // Bug fix for crbug.com/1197888. Don't let the extension update the tab if
+ // the user is dragging tabs.
+ if (!ExtensionTabUtil::IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
if (tab_strip->active_index() != tab_index) {
tab_strip->ActivateTabAt(tab_index);
DCHECK_EQ(contents, tab_strip->GetActiveWebContents());
@@ -1390,14 +1411,23 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
}
if (params->update_properties.highlighted.get()) {
+ // Bug fix for crbug.com/1197888. Don't let the extension update the tab if
+ // the user is dragging tabs.
+ if (!ExtensionTabUtil::IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
bool highlighted = *params->update_properties.highlighted;
if (highlighted != tab_strip->IsTabSelected(tab_index)) {
- if (!tab_strip->ToggleSelectionAt(tab_index))
- return RespondNow(Error(tabs_constants::kCannotHighlightTabs));
+ tab_strip->ToggleSelectionAt(tab_index);
}
}
if (params->update_properties.pinned.get()) {
+ // Bug fix for crbug.com/1197888. Don't let the extension update the tab if
+ // the user is dragging tabs.
+ if (!ExtensionTabUtil::IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
bool pinned = *params->update_properties.pinned;
tab_strip->SetTabPinned(tab_index, pinned);
@@ -1425,6 +1455,11 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
tabs_constants::kTabNotFoundError, base::NumberToString(opener_id))));
}
+ // Bug fix for crbug.com/1197888. Don't let the extension update the tab if
+ // the user is dragging tabs.
+ if (!ExtensionTabUtil::IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
if (tab_strip->GetIndexOfWebContents(opener_contents) ==
TabStripModel::kNoTab) {
return RespondNow(
@@ -1569,7 +1604,7 @@ bool TabsMoveFunction::MoveTab(int tab_id,
}
// Don't let the extension move the tab if the user is dragging tabs.
- if (!source_browser->window()->IsTabStripEditable()) {
+ if (!ExtensionTabUtil::IsTabStripEditable()) {
*error = tabs_constants::kTabStripNotEditableError;
return false;
}
@@ -1587,11 +1622,15 @@ bool TabsMoveFunction::MoveTab(int tab_id,
*new_index = inserted_index;
if (has_callback()) {
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(target_browser);
+ DCHECK(tab_strip_model);
content::WebContents* web_contents =
- target_browser->tab_strip_model()->GetWebContentsAt(inserted_index);
- tab_values->Append(CreateTabObjectHelper(
- web_contents, extension(), source_context_type(),
- target_browser->tab_strip_model(), inserted_index)
+ tab_strip_model->GetWebContentsAt(inserted_index);
+
+ tab_values->Append(CreateTabObjectHelper(web_contents, extension(),
+ source_context_type(),
+ tab_strip_model, inserted_index)
->ToValue());
}
@@ -1796,6 +1835,10 @@ ExtensionFunction::ResponseAction TabsGroupFunction::Run() {
return RespondNow(Error(std::move(error)));
}
+ DCHECK(target_browser);
+ if (!target_browser->window()->IsTabStripEditable())
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+
// Get all tab IDs from parameters.
std::vector<int> tab_ids;
if (params->options.tab_ids.as_integers) {
@@ -1848,7 +1891,10 @@ ExtensionFunction::ResponseAction TabsGroupFunction::Run() {
// Get the remaining group metadata and add the tabs to the group.
// At this point, we assume this is a valid action due to the checks above.
- TabStripModel* tab_strip = target_browser->tab_strip_model();
+ TabStripModel* tab_strip =
+ ExtensionTabUtil::GetEditableTabStripModel(target_browser);
+ if (!tab_strip)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
if (group.is_empty()) {
group = tab_strip->AddToNewGroup(tab_indices);
group_id = tab_groups_util::GetGroupId(group);
@@ -1927,7 +1973,13 @@ WebContents* TabsCaptureVisibleTabFunction::GetWebContentsForID(
if (!GetBrowserFromWindowID(chrome_details_, window_id, &browser, error))
return nullptr;
- WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip_model) {
+ *error = tabs_constants::kTabStripNotEditableError;
+ return nullptr;
+ }
+ WebContents* contents = tab_strip_model->GetActiveWebContents();
if (!contents) {
*error = "No active web contents to capture";
return nullptr;
@@ -2044,7 +2096,11 @@ ExtensionFunction::ResponseAction TabsDetectLanguageFunction::Run() {
browser = ChromeExtensionFunctionDetails(this).GetCurrentBrowser();
if (!browser)
return RespondNow(Error(tabs_constants::kNoCurrentWindowError));
- contents = browser->tab_strip_model()->GetActiveWebContents();
+ TabStripModel* tab_strip_model =
+ ExtensionTabUtil::GetEditableTabStripModel(browser);
+ if (!tab_strip_model)
+ return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
+ contents = tab_strip_model->GetActiveWebContents();
if (!contents)
return RespondNow(Error(tabs_constants::kNoSelectedTabError));
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
index 65b6e93eeaa..bb33332d802 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -131,6 +131,119 @@ void TabsApiUnitTest::TearDown() {
ExtensionServiceTestBase::TearDown();
}
+// Bug fix for crbug.com/1196309. Ensure that an extension can't update the tab
+// strip while a tab drag is in progress.
+TEST_F(TabsApiUnitTest, IsTabStripEditable) {
+ // Add a couple of web contents to the browser and get their tab IDs.
+ constexpr int kNumTabs = 2;
+ std::vector<int> tab_ids;
+ std::vector<content::WebContents*> web_contentses;
+ for (int i = 0; i < kNumTabs; ++i) {
+ std::unique_ptr<content::WebContents> contents(
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
+ CreateSessionServiceTabHelper(contents.get());
+ tab_ids.push_back(
+ sessions::SessionTabHelper::IdForTab(contents.get()).id());
+ web_contentses.push_back(contents.get());
+ browser()->tab_strip_model()->AppendWebContents(std::move(contents),
+ /* foreground */ true);
+ }
+ ASSERT_EQ(kNumTabs, browser()->tab_strip_model()->count());
+
+ ASSERT_TRUE(browser_window()->IsTabStripEditable());
+ auto extension = CreateTabsExtension();
+
+ // Succeed while tab drag not in progress.
+ {
+ std::string args = base::StringPrintf("[{\"tabs\": [%d]}]", 0);
+ scoped_refptr<TabsHighlightFunction> function =
+ base::MakeRefCounted<TabsHighlightFunction>();
+ function->set_extension(extension);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), args, browser(), api_test_utils::NONE));
+ }
+
+ // Start logical drag.
+ browser_window()->SetIsTabStripEditable(false);
+ ASSERT_FALSE(browser_window()->IsTabStripEditable());
+
+ // Succeed with updates that don't interact with the tab strip model.
+ {
+ const char* url = "https://example.com/";
+ std::string args =
+ base::StringPrintf("[%d, {\"url\": \"%s\"}]", tab_ids[0], url);
+ scoped_refptr<TabsUpdateFunction> function =
+ base::MakeRefCounted<TabsUpdateFunction>();
+ function->set_extension(extension);
+ std::unique_ptr<base::Value> value(
+ extension_function_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(), args, browser(), api_test_utils::NONE));
+ EXPECT_TRUE(value && value->is_dict());
+ EXPECT_EQ(*value->FindStringKey("pendingUrl"), url);
+ }
+
+ // Succeed while edit in progress and calling chrome.tabs.query.
+ {
+ const char* args = "[{}]";
+ scoped_refptr<TabsQueryFunction> function =
+ base::MakeRefCounted<TabsQueryFunction>();
+ function->set_extension(extension);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), args, browser(), api_test_utils::NONE));
+ }
+
+ // Succeed while edit in progress and calling chrome.tabs.get.
+ {
+ std::string args = base::StringPrintf("[%d]", tab_ids[0]);
+ scoped_refptr<TabsGetFunction> function =
+ base::MakeRefCounted<TabsGetFunction>();
+ function->set_extension(extension);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), args, browser(), api_test_utils::NONE));
+ }
+
+ // Bug fix for crbug.com/1198717. Error updating tabs while drag in progress.
+ {
+ std::string args =
+ base::StringPrintf("[%d, {\"highlighted\": true}]", tab_ids[0]);
+ auto function = base::MakeRefCounted<TabsUpdateFunction>();
+ function->set_extension(extension);
+ std::string error =
+ extension_function_test_utils::RunFunctionAndReturnError(
+ function.get(), args, browser());
+ EXPECT_EQ(tabs_constants::kTabStripNotEditableError, error);
+ }
+
+ // Error highlighting tab while drag in progress.
+ {
+ std::string args = base::StringPrintf("[{\"tabs\": [%d]}]", tab_ids[0]);
+ auto function = base::MakeRefCounted<TabsHighlightFunction>();
+ function->set_extension(extension);
+ std::string error =
+ extension_function_test_utils::RunFunctionAndReturnError(
+ function.get(), args, browser(), api_test_utils::NONE);
+ EXPECT_EQ(tabs_constants::kTabStripNotEditableError, error);
+ }
+
+ // Bug fix for crbug.com/1197146. Tab group modification during drag.
+ {
+ std::string args = base::StringPrintf("[{\"tabIds\": [%d]}]", tab_ids[0]);
+ scoped_refptr<TabsGroupFunction> function =
+ base::MakeRefCounted<TabsGroupFunction>();
+ function->set_extension(extension);
+ std::string error =
+ extension_function_test_utils::RunFunctionAndReturnError(
+ function.get(), args, browser());
+ EXPECT_EQ(tabs_constants::kTabStripNotEditableError, error);
+ }
+
+ // TODO(solomonkinard): Consider adding tests for drag cancellation.
+
+ // Clean up.
+ while (!browser()->tab_strip_model()->empty())
+ browser()->tab_strip_model()->DetachWebContentsAt(0);
+}
+
TEST_F(TabsApiUnitTest, QueryWithoutTabsPermission) {
GURL tab_urls[] = {GURL("http://www.google.com"),
GURL("http://www.example.com"),
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
index 8bd3d4edf2e..e438ed25f0a 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
@@ -92,6 +92,8 @@ const char kCannotDiscardTab[] = "Cannot discard tab with id: *.";
const char kCannotFindTabToDiscard[] = "Cannot find a tab to discard.";
const char kTabStripNotEditableError[] =
"Tabs cannot be edited right now (user may be dragging a tab).";
+const char kTabStripNotEditableQueryError[] =
+ "Tabs cannot be queried right now (user may be dragging a tab).";
const char kNoSelectedTabError[] = "No selected tab";
const char kNoHighlightedTabError[] = "No highlighted tab";
const char kIncognitoModeIsDisabled[] = "Incognito mode is disabled.";
@@ -124,9 +126,6 @@ const char kGroupParamsError[] =
const char kCannotNavigateToDevtools[] =
"Cannot navigate to a devtools:// page without either the devtools or "
"debugger permission.";
-const char kCannotHighlightTabs[] =
- "Cannot change tab highlight. This may for instance be due to user "
- "dragging in progress.";
} // namespace tabs_constants
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
index 7278abcda41..3e257f524d8 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -91,6 +91,7 @@ extern const char kTabNotFoundError[];
extern const char kCannotDiscardTab[];
extern const char kCannotFindTabToDiscard[];
extern const char kTabStripNotEditableError[];
+extern const char kTabStripNotEditableQueryError[];
extern const char kNoHighlightedTabError[];
extern const char kNoSelectedTabError[];
extern const char kIncognitoModeIsDisabled[];
@@ -110,7 +111,6 @@ extern const char kBrowserWindowNotAllowed[];
extern const char kLockedFullscreenModeNewTabError[];
extern const char kGroupParamsError[];
extern const char kCannotNavigateToDevtools[];
-extern const char kCannotHighlightTabs[];
} // namespace tabs_constants
} // namespace extensions
diff --git a/chromium/chrome/browser/ui/webui/invalidations/invalidations_message_handler.cc b/chromium/chrome/browser/ui/webui/invalidations/invalidations_message_handler.cc
index 5653f0c43e7..5b7b65716b1 100644
--- a/chromium/chrome/browser/ui/webui/invalidations/invalidations_message_handler.cc
+++ b/chromium/chrome/browser/ui/webui/invalidations/invalidations_message_handler.cc
@@ -33,7 +33,12 @@ invalidation::ProfileInvalidationProvider* GetInvalidationProvider(
InvalidationsMessageHandler::InvalidationsMessageHandler() : logger_(nullptr) {}
-InvalidationsMessageHandler::~InvalidationsMessageHandler() = default;
+InvalidationsMessageHandler::~InvalidationsMessageHandler() {
+ // This handler can be destroyed without OnJavascriptDisallowed() ever being
+ // called (https://crbug.com/1199198). Call it to ensure that `this` is
+ // removed as an observer.
+ OnJavascriptDisallowed();
+}
void InvalidationsMessageHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(