Skip to content

Commit 6fbc9d4

Browse files
authored
Merge branch 'trunk' into release-preparation-4.36.0
2 parents d35c500 + 8e84f0d commit 6fbc9d4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+6675
-7887
lines changed

WORKSPACE

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ rules_closure_toolchains()
2626

2727
http_archive(
2828
name = "rules_rust",
29-
integrity = "sha256-eEXiHXSGUH6qD1bdI5KXZ/B04m0wIUeoyM7pmujzbbQ=",
30-
urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.55.5/rules_rust-0.55.5.tar.gz"],
29+
integrity = "sha256-YrnH/f8jCpEqGAU+keNqauc+QSde9egtcFXqPtJuee4=",
30+
urls = ["https://github.com/bazelbuild/rules_rust/releases/download/0.65.0/rules_rust-0.65.0.tar.gz"],
3131
)
3232

3333
load("@rules_rust//rust:repositories.bzl", "rules_rust_dependencies", "rust_register_toolchains")
3434

3535
rules_rust_dependencies()
3636

37-
rust_register_toolchains()
37+
rust_register_toolchains(versions = ["1.89.0"])
3838

3939
load("@rules_rust//crate_universe:defs.bzl", "crates_repository")
4040

@@ -48,3 +48,7 @@ crates_repository(
4848
load("@crates//:defs.bzl", "crate_repositories")
4949

5050
crate_repositories()
51+
52+
load("@rules_rust//cargo:deps.bzl", "cargo_dependencies")
53+
54+
cargo_dependencies()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// <copyright file="IBaseNavigationInfo.cs" company="Selenium Committers">
2+
// Licensed to the Software Freedom Conservancy (SFC) under one
3+
// or more contributor license agreements. See the NOTICE file
4+
// distributed with this work for additional information
5+
// regarding copyright ownership. The SFC licenses this file
6+
// to you under the Apache License, Version 2.0 (the
7+
// "License"); you may not use this file except in compliance
8+
// with the License. You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing,
13+
// software distributed under the License is distributed on an
14+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
// KIND, either express or implied. See the License for the
16+
// specific language governing permissions and limitations
17+
// under the License.
18+
// </copyright>
19+
20+
using System;
21+
22+
namespace OpenQA.Selenium.BiDi.BrowsingContext;
23+
24+
public interface IBaseNavigationInfo
25+
{
26+
BrowsingContext Context { get; }
27+
28+
Navigation? Navigation { get; }
29+
30+
DateTimeOffset Timestamp { get; }
31+
32+
string Url { get; }
33+
}

dotnet/src/webdriver/BiDi/BrowsingContext/NavigationInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@
2222
namespace OpenQA.Selenium.BiDi.BrowsingContext;
2323

2424
public sealed record NavigationInfo(BiDi BiDi, BrowsingContext Context, Navigation? Navigation, DateTimeOffset Timestamp, string Url)
25-
: BrowsingContextEventArgs(BiDi, Context);
25+
: BrowsingContextEventArgs(BiDi, Context), IBaseNavigationInfo;

dotnet/src/webdriver/BiDi/Communication/Broker.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,21 +123,33 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
123123

124124
private async Task ReceiveMessagesAsync(CancellationToken cancellationToken)
125125
{
126-
while (!cancellationToken.IsCancellationRequested)
126+
try
127127
{
128-
try
128+
while (!cancellationToken.IsCancellationRequested)
129129
{
130130
var data = await _transport.ReceiveAsync(cancellationToken).ConfigureAwait(false);
131131

132-
ProcessReceivedMessage(data);
133-
}
134-
catch (Exception ex)
135-
{
136-
if (cancellationToken.IsCancellationRequested is not true && _logger.IsEnabled(LogEventLevel.Error))
132+
try
137133
{
138-
_logger.Error($"Couldn't process received BiDi remote message: {ex}");
134+
ProcessReceivedMessage(data);
139135
}
136+
catch (Exception ex)
137+
{
138+
if (_logger.IsEnabled(LogEventLevel.Error))
139+
{
140+
_logger.Error($"Unhandled error occured while processing remote message: {ex}");
141+
}
142+
}
143+
}
144+
}
145+
catch (Exception ex) when (ex is not OperationCanceledException)
146+
{
147+
if (_logger.IsEnabled(LogEventLevel.Error))
148+
{
149+
_logger.Error($"Unhandled error occured while receiving remote messages: {ex}");
140150
}
151+
152+
throw;
141153
}
142154
}
143155

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import React from 'react'
19+
import { IconButton, Tooltip } from '@mui/material'
20+
import { LightMode, DarkMode, AutoMode } from '@mui/icons-material'
21+
import { useTheme } from '../../contexts/ThemeContext'
22+
23+
export const ThemeToggle: React.FC = () => {
24+
const { themeMode, setThemeMode } = useTheme()
25+
26+
const handleClick = () => {
27+
const nextMode = themeMode === 'light' ? 'dark' : themeMode === 'dark' ? 'system' : 'light'
28+
setThemeMode(nextMode)
29+
}
30+
31+
const getIcon = () => {
32+
if (themeMode === 'light') return <LightMode />
33+
if (themeMode === 'dark') return <DarkMode />
34+
return <AutoMode />
35+
}
36+
37+
const getTooltip = () => {
38+
if (themeMode === 'light') return 'Switch to dark mode'
39+
if (themeMode === 'dark') return 'Switch to system mode'
40+
return 'Switch to light mode'
41+
}
42+
43+
return (
44+
<Tooltip title={getTooltip()}>
45+
<IconButton
46+
color="inherit"
47+
onClick={handleClick}
48+
aria-label="Toggle theme"
49+
>
50+
{getIcon()}
51+
</IconButton>
52+
</Tooltip>
53+
)
54+
}

javascript/grid-ui/src/components/TopBar/TopBar.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { Menu as MenuIcon } from '@mui/icons-material'
2727
import { Help as HelpIcon } from '@mui/icons-material'
2828
import React from 'react'
2929
import seleniumGridLogo from '../../assets/selenium-grid-logo.svg'
30+
import { ThemeToggle } from '../ThemeToggle/ThemeToggle'
3031

3132
const AppBar = styled(MuiAppBar)(({ theme }) => ({
3233
zIndex: theme.zIndex.drawer + 1,
@@ -93,14 +94,16 @@ function TopBar (props): JSX.Element {
9394
component="h1"
9495
variant="h4"
9596
noWrap
97+
sx={{ color: (theme) => theme.palette.mode === 'dark' ? 'primary.main' : 'inherit' }}
9698
>
9799
Selenium Grid
98100
</Typography>
99-
<Typography variant="body2">
101+
<Typography variant="body2" sx={{ color: (theme) => theme.palette.mode === 'dark' ? 'primary.main' : 'inherit' }}>
100102
{subheader}
101103
</Typography>
102104
</Box>
103105
</Box>
106+
<ThemeToggle />
104107
</Toolbar>
105108
</AppBar>
106109
</Box>
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
19+
import React, { createContext, useContext, useState, useEffect } from 'react'
20+
import { ThemeProvider } from '@mui/material/styles'
21+
import { CssBaseline } from '@mui/material'
22+
import { lightTheme, darkTheme } from '../theme/themes'
23+
24+
type ThemeMode = 'light' | 'dark' | 'system'
25+
26+
const ThemeContext = createContext<{
27+
themeMode: ThemeMode
28+
setThemeMode: (mode: ThemeMode) => void
29+
}>({
30+
themeMode: 'system',
31+
setThemeMode: () => {}
32+
})
33+
34+
export const useTheme = () => useContext(ThemeContext)
35+
36+
export const CustomThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
37+
const [themeMode, setThemeMode] = useState<ThemeMode>('system')
38+
const [systemPrefersDark, setSystemPrefersDark] = useState(false)
39+
40+
useEffect(() => {
41+
if (typeof window !== 'undefined' && window.localStorage) {
42+
const saved = localStorage.getItem('theme-mode') as ThemeMode
43+
if (saved) setThemeMode(saved)
44+
}
45+
if (typeof window !== 'undefined' && window.matchMedia) {
46+
setSystemPrefersDark(window.matchMedia('(prefers-color-scheme: dark)').matches)
47+
}
48+
}, [])
49+
50+
useEffect(() => {
51+
if (typeof window !== 'undefined' && window.localStorage) {
52+
localStorage.setItem('theme-mode', themeMode)
53+
}
54+
}, [themeMode])
55+
56+
useEffect(() => {
57+
if (typeof window !== 'undefined' && window.matchMedia) {
58+
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
59+
const handler = (e: MediaQueryListEvent) => setSystemPrefersDark(e.matches)
60+
mediaQuery.addEventListener('change', handler)
61+
return () => mediaQuery.removeEventListener('change', handler)
62+
}
63+
}, [])
64+
65+
const isDark = themeMode === 'dark' || (themeMode === 'system' && systemPrefersDark)
66+
const currentTheme = isDark ? darkTheme : lightTheme
67+
68+
return (
69+
<ThemeContext.Provider value={{ themeMode, setThemeMode }}>
70+
<ThemeProvider theme={currentTheme}>
71+
<CssBaseline />
72+
{children}
73+
</ThemeProvider>
74+
</ThemeContext.Provider>
75+
)
76+
}

javascript/grid-ui/src/index.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18-
import { CssBaseline } from '@mui/material'
19-
import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles'
18+
import { StyledEngineProvider } from '@mui/material/styles'
2019
import React from 'react'
2120
import ReactDOM from 'react-dom/client'
2221
import { HashRouter as Router } from 'react-router-dom'
2322
import App from './App'
2423
import * as serviceWorker from './serviceWorker'
25-
import theme from './theme/theme'
24+
import { CustomThemeProvider } from './contexts/ThemeContext'
2625
import './index.css'
2726

2827
const root = ReactDOM.createRoot(
@@ -32,12 +31,11 @@ const root = ReactDOM.createRoot(
3231
root.render(
3332
<React.StrictMode>
3433
<StyledEngineProvider injectFirst>
35-
<ThemeProvider theme={theme}>
36-
<CssBaseline/>
34+
<CustomThemeProvider>
3735
<Router>
3836
<App/>
3937
</Router>
40-
</ThemeProvider>
38+
</CustomThemeProvider>
4139
</StyledEngineProvider>
4240
</React.StrictMode>
4341
)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
import { lightTheme } from '../../theme/themes'
19+
20+
export const useTheme = jest.fn(() => ({
21+
themeMode: 'light',
22+
setThemeMode: jest.fn(),
23+
currentTheme: lightTheme,
24+
isDark: false
25+
}))

0 commit comments

Comments
 (0)