mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
feat: support chrome.tabs.onZoomChanged
This commit is contained in:
@@ -686,6 +686,10 @@ filenames = {
|
||||
"shell/browser/extensions/api/streams_private/streams_private_api.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_api.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_event_router.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_event_router.h",
|
||||
"shell/browser/extensions/api/tabs/tabs_window_api.cc",
|
||||
"shell/browser/extensions/api/tabs/tabs_window_api.h",
|
||||
"shell/browser/extensions/electron_browser_context_keyed_service_factories.cc",
|
||||
"shell/browser/extensions/electron_browser_context_keyed_service_factories.h",
|
||||
"shell/browser/extensions/electron_component_extension_resource_manager.cc",
|
||||
|
||||
@@ -164,6 +164,8 @@
|
||||
#include "extensions/browser/script_executor.h"
|
||||
#include "extensions/browser/view_type_utils.h"
|
||||
#include "extensions/common/mojom/view_type.mojom.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_event_router.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_window_api.h"
|
||||
#include "shell/browser/extensions/electron_extension_web_contents_observer.h"
|
||||
#endif
|
||||
|
||||
@@ -893,6 +895,14 @@ void WebContents::InitZoomController(content::WebContents* web_contents,
|
||||
if (options.Get(options::kZoomFactor, &zoom_factor))
|
||||
zoom_controller_->SetDefaultZoomFactor(zoom_factor);
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
auto* tabs_window_api = extensions::TabsWindowsAPI::Get(GetBrowserContext());
|
||||
if (tabs_window_api) {
|
||||
tabs_window_api->tabs_event_router()->RegisterForTabNotifications(
|
||||
web_contents);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Nothing to do with ZoomController, but this function gets called in all
|
||||
// init cases!
|
||||
content::RenderViewHost* host = web_contents->GetRenderViewHost();
|
||||
|
||||
126
shell/browser/extensions/api/tabs/tabs_event_router.cc
Normal file
126
shell/browser/extensions/api/tabs/tabs_event_router.cc
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2023 Microsoft, GmbH
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/extensions/api/tabs/tabs_event_router.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "components/zoom/zoom_controller.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "extensions/common/features/feature.h"
|
||||
#include "extensions/common/mojom/event_dispatcher.mojom-forward.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_window_api.h"
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/common/extensions/api/tabs.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "third_party/blink/public/common/page/page_zoom.h"
|
||||
|
||||
using base::Value;
|
||||
using content::WebContents;
|
||||
using zoom::ZoomController;
|
||||
|
||||
using electron::WebContentsZoomController;
|
||||
|
||||
namespace extensions {
|
||||
|
||||
// namespace {
|
||||
// void ZoomModeToZoomSettings(ZoomController::ZoomMode zoom_mode,
|
||||
// api::tabs::ZoomSettings* zoom_settings) {
|
||||
// DCHECK(zoom_settings);
|
||||
// switch (zoom_mode) {
|
||||
// case ZoomController::ZOOM_MODE_DEFAULT:
|
||||
// zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
|
||||
// zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_ORIGIN;
|
||||
// break;
|
||||
// case ZoomController::ZOOM_MODE_ISOLATED:
|
||||
// zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_AUTOMATIC;
|
||||
// zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
// break;
|
||||
// case ZoomController::ZOOM_MODE_MANUAL:
|
||||
// zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_MANUAL;
|
||||
// zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
// break;
|
||||
// case ZoomController::ZOOM_MODE_DISABLED:
|
||||
// zoom_settings->mode = api::tabs::ZOOM_SETTINGS_MODE_DISABLED;
|
||||
// zoom_settings->scope = api::tabs::ZOOM_SETTINGS_SCOPE_PER_TAB;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } // namespace
|
||||
|
||||
TabsEventRouter::TabsEventRouter(content::BrowserContext* context)
|
||||
: context_(context) {}
|
||||
|
||||
TabsEventRouter::~TabsEventRouter() = default;
|
||||
|
||||
void TabsEventRouter::OnZoomControllerDestroyed(
|
||||
WebContentsZoomController* zoom_controller) {
|
||||
if (zoom_scoped_observations_.IsObservingSource(zoom_controller)) {
|
||||
zoom_scoped_observations_.RemoveObservation(zoom_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void TabsEventRouter::OnZoomChanged(
|
||||
const electron::WebContentsZoomController::ZoomChangedEventData& data) {
|
||||
DCHECK(web_contents);
|
||||
auto* api_web_contents = electron::api::WebContents::From(data.web_contents);
|
||||
int tab_id = api_web_contents ? api_web_contents->ID() : -1;
|
||||
if (tab_id < 0)
|
||||
return;
|
||||
|
||||
// Prepare the zoom change information.
|
||||
api::tabs::OnZoomChange::ZoomChangeInfo zoom_change_info;
|
||||
zoom_change_info.tab_id = tab_id;
|
||||
zoom_change_info.old_zoom_factor =
|
||||
blink::PageZoomLevelToZoomFactor(data.old_zoom_level);
|
||||
zoom_change_info.new_zoom_factor =
|
||||
blink::PageZoomLevelToZoomFactor(data.new_zoom_level);
|
||||
// ZoomModeToZoomSettings(data.zoom_mode, &zoom_change_info.zoom_settings);
|
||||
|
||||
// Dispatch the |onZoomChange| event.
|
||||
DispatchEvent(data.web_contents->GetBrowserContext(),
|
||||
events::TABS_ON_ZOOM_CHANGE,
|
||||
api::tabs::OnZoomChange::kEventName,
|
||||
api::tabs::OnZoomChange::Create(zoom_change_info),
|
||||
EventRouter::USER_GESTURE_UNKNOWN);
|
||||
}
|
||||
|
||||
void TabsEventRouter::DispatchEvent(
|
||||
content::BrowserContext* context,
|
||||
events::HistogramValue histogram_value,
|
||||
const std::string& event_name,
|
||||
base::Value::List args,
|
||||
EventRouter::UserGestureState user_gesture) {
|
||||
EventRouter* event_router = EventRouter::Get(context);
|
||||
if (!event_router)
|
||||
return;
|
||||
|
||||
auto event = std::make_unique<Event>(histogram_value, event_name,
|
||||
std::move(args), context);
|
||||
event->user_gesture = user_gesture;
|
||||
event_router->BroadcastEvent(std::move(event));
|
||||
}
|
||||
|
||||
void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) {
|
||||
zoom_scoped_observations_.AddObservation(
|
||||
WebContentsZoomController::FromWebContents(contents));
|
||||
}
|
||||
|
||||
void TabsEventRouter::UnregisterForTabNotifications(WebContents* contents) {
|
||||
if (auto* zoom_controller =
|
||||
WebContentsZoomController::FromWebContents(contents);
|
||||
zoom_scoped_observations_.IsObservingSource(zoom_controller)) {
|
||||
zoom_scoped_observations_.RemoveObservation(zoom_controller);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace extensions
|
||||
74
shell/browser/extensions/api/tabs/tabs_event_router.h
Normal file
74
shell/browser/extensions/api/tabs/tabs_event_router.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2013 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/scoped_multi_source_observation.h"
|
||||
#include "base/scoped_observation.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "extensions/browser/event_router.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_api.h"
|
||||
#include "shell/browser/web_contents_zoom_controller.h"
|
||||
#include "shell/browser/web_contents_zoom_observer.h"
|
||||
|
||||
namespace content {
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
namespace extensions {
|
||||
|
||||
// The TabsEventRouter listens to tab events and routes them to listeners inside
|
||||
// extension process renderers.
|
||||
// TabsEventRouter will only route events from windows/tabs within a context to
|
||||
// extension processes in the same context.
|
||||
class TabsEventRouter : public electron::WebContentsZoomObserver {
|
||||
public:
|
||||
explicit TabsEventRouter(content::BrowserContext* context);
|
||||
|
||||
TabsEventRouter(const TabsEventRouter&) = delete;
|
||||
TabsEventRouter& operator=(const TabsEventRouter&) = delete;
|
||||
|
||||
~TabsEventRouter() override;
|
||||
|
||||
// WebContentsZoomController::Observer
|
||||
void OnZoomChanged(
|
||||
const electron::WebContentsZoomController::ZoomChangedEventData& data)
|
||||
override;
|
||||
void OnZoomControllerDestroyed(
|
||||
electron::WebContentsZoomController* controller) override;
|
||||
|
||||
// Register ourselves to receive the various notifications we are interested
|
||||
// in for a tab. Also create tab entry to observe web contents notifications.
|
||||
void RegisterForTabNotifications(content::WebContents* contents);
|
||||
|
||||
private:
|
||||
// The DispatchEvent methods forward events to the |context|'s event router.
|
||||
// The TabsEventRouter listens to events for all contexts,
|
||||
// so we avoid duplication by dropping events destined for other contexts.
|
||||
void DispatchEvent(content::BrowserContext* context,
|
||||
events::HistogramValue histogram_value,
|
||||
const std::string& event_name,
|
||||
base::Value::List args,
|
||||
EventRouter::UserGestureState user_gesture);
|
||||
|
||||
// Removes notifications and tab entry added in RegisterForTabNotifications.
|
||||
void UnregisterForTabNotifications(content::WebContents* contents);
|
||||
|
||||
// The main context that owns this event router.
|
||||
raw_ptr<content::BrowserContext> context_;
|
||||
|
||||
base::ScopedMultiSourceObservation<electron::WebContentsZoomController,
|
||||
electron::WebContentsZoomObserver>
|
||||
zoom_scoped_observations_{this};
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_EVENT_ROUTER_H_
|
||||
57
shell/browser/extensions/api/tabs/tabs_window_api.cc
Normal file
57
shell/browser/extensions/api/tabs/tabs_window_api.cc
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2012 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/extensions/api/tabs/tabs_window_api.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/lazy_instance.h"
|
||||
#include "extensions/browser/event_router.h"
|
||||
#include "extensions/browser/extension_system.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_event_router.h"
|
||||
#include "shell/common/extensions/api/tabs.h"
|
||||
|
||||
namespace extensions {
|
||||
|
||||
TabsWindowsAPI::TabsWindowsAPI(content::BrowserContext* context)
|
||||
: browser_context_(context) {
|
||||
EventRouter* event_router = EventRouter::Get(browser_context_);
|
||||
|
||||
// Tabs API Events.
|
||||
event_router->RegisterObserver(this, api::tabs::OnZoomChange::kEventName);
|
||||
}
|
||||
|
||||
TabsWindowsAPI::~TabsWindowsAPI() = default;
|
||||
|
||||
// static
|
||||
TabsWindowsAPI* TabsWindowsAPI::Get(content::BrowserContext* context) {
|
||||
return BrowserContextKeyedAPIFactory<TabsWindowsAPI>::Get(context);
|
||||
}
|
||||
|
||||
TabsEventRouter* TabsWindowsAPI::tabs_event_router() {
|
||||
if (!tabs_event_router_.get()) {
|
||||
tabs_event_router_ = std::make_unique<TabsEventRouter>(browser_context_);
|
||||
}
|
||||
return tabs_event_router_.get();
|
||||
}
|
||||
|
||||
void TabsWindowsAPI::Shutdown() {
|
||||
EventRouter::Get(browser_context_)->UnregisterObserver(this);
|
||||
}
|
||||
|
||||
static base::LazyInstance<BrowserContextKeyedAPIFactory<TabsWindowsAPI>>::
|
||||
DestructorAtExit g_tabs_windows_api_factory = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
BrowserContextKeyedAPIFactory<TabsWindowsAPI>*
|
||||
TabsWindowsAPI::GetFactoryInstance() {
|
||||
return g_tabs_windows_api_factory.Pointer();
|
||||
}
|
||||
|
||||
void TabsWindowsAPI::OnListenerAdded(const EventListenerInfo& details) {
|
||||
// Initialize the event routers.
|
||||
tabs_event_router();
|
||||
EventRouter::Get(browser_context_)->UnregisterObserver(this);
|
||||
}
|
||||
|
||||
} // namespace extensions
|
||||
53
shell/browser/extensions/api/tabs/tabs_window_api.h
Normal file
53
shell/browser/extensions/api/tabs/tabs_window_api.h
Normal file
@@ -0,0 +1,53 @@
|
||||
// Copyright 2012 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_WINDOWS_API_H_
|
||||
#define SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_WINDOWS_API_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "extensions/browser/browser_context_keyed_api_factory.h"
|
||||
#include "extensions/browser/event_router.h"
|
||||
|
||||
namespace extensions {
|
||||
class TabsEventRouter;
|
||||
|
||||
class TabsWindowsAPI : public BrowserContextKeyedAPI,
|
||||
public EventRouter::Observer {
|
||||
public:
|
||||
explicit TabsWindowsAPI(content::BrowserContext* context);
|
||||
~TabsWindowsAPI() override;
|
||||
|
||||
// Convenience method to get the TabsWindowsAPI for a BrowserContext.
|
||||
static TabsWindowsAPI* Get(content::BrowserContext* context);
|
||||
|
||||
TabsEventRouter* tabs_event_router();
|
||||
|
||||
// KeyedService implementation.
|
||||
void Shutdown() override;
|
||||
|
||||
// BrowserContextKeyedAPI implementation.
|
||||
static BrowserContextKeyedAPIFactory<TabsWindowsAPI>* GetFactoryInstance();
|
||||
|
||||
// EventRouter::Observer implementation.
|
||||
void OnListenerAdded(const extensions::EventListenerInfo& details) override;
|
||||
|
||||
private:
|
||||
friend class BrowserContextKeyedAPIFactory<TabsWindowsAPI>;
|
||||
|
||||
raw_ptr<content::BrowserContext> browser_context_;
|
||||
|
||||
// BrowserContextKeyedAPI implementation.
|
||||
static const char* service_name() {
|
||||
return "TabsWindowsAPI";
|
||||
}
|
||||
|
||||
std::unique_ptr<TabsEventRouter> tabs_event_router_;
|
||||
};
|
||||
|
||||
} // namespace extensions
|
||||
|
||||
#endif // SHELL_BROWSER_EXTENSIONS_API_TABS_TABS_WINDOWS_API_H_
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "shell/browser/extensions/electron_browser_context_keyed_service_factories.h"
|
||||
|
||||
#include "extensions/browser/updater/update_service_factory.h"
|
||||
#include "shell/browser/extensions/api/tabs/tabs_window_api.h"
|
||||
#include "shell/browser/extensions/electron_extension_system_factory.h"
|
||||
|
||||
namespace extensions::electron {
|
||||
@@ -14,6 +15,8 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
|
||||
// extensions embedders (and namely chrome.)
|
||||
UpdateServiceFactory::GetInstance();
|
||||
|
||||
TabsWindowsAPI::GetFactoryInstance();
|
||||
|
||||
ElectronExtensionSystemFactory::GetInstance();
|
||||
}
|
||||
|
||||
|
||||
@@ -878,7 +878,12 @@ describe('chrome extensions', () => {
|
||||
const [,, responseString] = await once(w.webContents, 'console-message');
|
||||
|
||||
const response = JSON.parse(responseString);
|
||||
expect(response).to.deep.equal(2);
|
||||
expect(response).to.deep.equal({
|
||||
newZoomFactor: 2,
|
||||
oldZoomFactor: 1.2,
|
||||
tabId: 1,
|
||||
zoomSettings: {}
|
||||
});
|
||||
});
|
||||
|
||||
it('getZoomSettings', async () => {
|
||||
|
||||
@@ -12,10 +12,9 @@ const handleRequest = (request, sender, sendResponse) => {
|
||||
|
||||
case 'setZoom': {
|
||||
const [zoom] = args;
|
||||
chrome.tabs.setZoom(tabId, zoom).then(async () => {
|
||||
const updatedZoom = await chrome.tabs.getZoom(tabId);
|
||||
sendResponse(updatedZoom);
|
||||
});
|
||||
|
||||
chrome.tabs.onZoomChange.addListener(sendResponse);
|
||||
chrome.tabs.setZoom(tabId, zoom);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user