diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs index 82f55589686..a583a75d1d9 100644 --- a/components/constellation/constellation.rs +++ b/components/constellation/constellation.rs @@ -4738,6 +4738,14 @@ where WebDriverCommandMsg::FocusWebView(webview_id) => { self.handle_focus_web_view(webview_id); }, + WebDriverCommandMsg::IsWebViewOpen(webview_id, response_sender) => { + let is_open = self.webviews.get(webview_id).is_some(); + let _ = response_sender.send(is_open); + }, + WebDriverCommandMsg::IsBrowsingContextOpen(browsing_context_id, response_sender) => { + let is_open = self.browsing_contexts.contains_key(&browsing_context_id); + let _ = response_sender.send(is_open); + }, WebDriverCommandMsg::GetWindowSize(webview_id, response_sender) => { let browsing_context_id = BrowsingContextId::from(webview_id); let size = self diff --git a/components/shared/embedder/webdriver.rs b/components/shared/embedder/webdriver.rs index 4f58c10fb6f..f4f9cd5d509 100644 --- a/components/shared/embedder/webdriver.rs +++ b/components/shared/embedder/webdriver.rs @@ -84,6 +84,10 @@ pub enum WebDriverCommandMsg { CloseWebView(WebViewId), /// Focus the webview associated with the provided id. FocusWebView(WebViewId), + /// Check whether top-level browsing context is open. + IsWebViewOpen(WebViewId, IpcSender), + /// Check whether browsing context is open. + IsBrowsingContextOpen(BrowsingContextId, IpcSender), } #[derive(Debug, Deserialize, Serialize)] diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs index f2638764df6..cd479d7fae6 100644 --- a/components/webdriver_server/lib.rs +++ b/components/webdriver_server/lib.rs @@ -667,6 +667,7 @@ impl Handler { cmd_msg: WebDriverScriptCommand, ) -> WebDriverResult<()> { let browsing_context_id = self.session()?.browsing_context_id; + self.verify_browsing_context_is_open(browsing_context_id)?; let msg = EmbedderToConstellationMessage::WebDriverCommand( WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg), ); @@ -675,7 +676,9 @@ impl Handler { } fn top_level_script_command(&self, cmd_msg: WebDriverScriptCommand) -> WebDriverResult<()> { - let browsing_context_id = BrowsingContextId::from(self.session()?.webview_id); + let webview_id = self.session()?.webview_id; + self.verify_top_level_browsing_context_is_open(webview_id)?; + let browsing_context_id = BrowsingContextId::from(webview_id); let msg = EmbedderToConstellationMessage::WebDriverCommand( WebDriverCommandMsg::ScriptCommand(browsing_context_id, cmd_msg), ); @@ -683,7 +686,14 @@ impl Handler { Ok(()) } + /// fn handle_get(&self, parameters: &GetParameters) -> WebDriverResult { + let webview_id = self.session()?.webview_id; + // Step 2. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; + // Step 3. If URL is not an absolute URL or is not an absolute URL with fragment + // or not a local scheme, return error with error code invalid argument. let url = match ServoUrl::parse(¶meters.url[..]) { Ok(url) => url, Err(_) => { @@ -694,8 +704,6 @@ impl Handler { }, }; - let webview_id = self.session()?.webview_id; - let cmd_msg = WebDriverCommandMsg::LoadUrl(webview_id, url, self.load_status_sender.clone()); self.constellation_chan @@ -732,6 +740,9 @@ impl Handler { fn handle_window_size(&self) -> WebDriverResult { let (sender, receiver) = ipc::channel().unwrap(); let webview_id = self.session()?.webview_id; + + self.verify_top_level_browsing_context_is_open(webview_id)?; + let cmd_msg = WebDriverCommandMsg::GetWindowSize(webview_id, sender); self.constellation_chan @@ -764,6 +775,11 @@ impl Handler { let height = params.height.unwrap_or(0); let size = Size2D::new(width as u32, height as u32); let webview_id = self.session()?.webview_id; + // TODO: Return some other error earlier if the size is invalid. + + // Step 12. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; let cmd_msg = WebDriverCommandMsg::SetWindowSize(webview_id, size.to_i32(), sender.clone()); self.constellation_chan @@ -793,6 +809,10 @@ impl Handler { } fn handle_is_enabled(&self, element: &WebElement) -> WebDriverResult { + // Step 1. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?; + let (sender, receiver) = ipc::channel().unwrap(); self.top_level_script_command(WebDriverScriptCommand::IsEnabled( @@ -809,6 +829,10 @@ impl Handler { } fn handle_is_selected(&self, element: &WebElement) -> WebDriverResult { + // Step 1. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?; + let (sender, receiver) = ipc::channel().unwrap(); self.top_level_script_command(WebDriverScriptCommand::IsSelected( @@ -826,6 +850,9 @@ impl Handler { fn handle_go_back(&self) -> WebDriverResult { let webview_id = self.session()?.webview_id; + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; let direction = TraversalDirection::Back(1); let msg = EmbedderToConstellationMessage::TraverseHistory(webview_id, direction); self.constellation_chan.send(msg).unwrap(); @@ -834,6 +861,9 @@ impl Handler { fn handle_go_forward(&self) -> WebDriverResult { let webview_id = self.session()?.webview_id; + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; let direction = TraversalDirection::Forward(1); let msg = EmbedderToConstellationMessage::TraverseHistory(webview_id, direction); self.constellation_chan.send(msg).unwrap(); @@ -842,6 +872,9 @@ impl Handler { fn handle_refresh(&self) -> WebDriverResult { let webview_id = self.session()?.webview_id; + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(webview_id)?; let cmd_msg = WebDriverCommandMsg::Refresh(webview_id, self.load_status_sender.clone()); self.constellation_chan @@ -864,6 +897,9 @@ impl Handler { fn handle_window_handle(&self) -> WebDriverResult { let session = self.session.as_ref().unwrap(); + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(session.webview_id)?; match session.window_handles.get(&session.webview_id) { Some(handle) => Ok(WebDriverResponse::Generic(ValueResponse( serde_json::to_value(handle)?, @@ -929,10 +965,13 @@ impl Handler { } } + /// fn handle_close_window(&mut self) -> WebDriverResult { { + let webview_id = self.session()?.webview_id; + self.verify_top_level_browsing_context_is_open(webview_id)?; let session = self.session_mut().unwrap(); - session.window_handles.remove(&session.webview_id); + session.window_handles.remove(&webview_id); let cmd_msg = WebDriverCommandMsg::CloseWebView(session.webview_id); self.constellation_chan .send(EmbedderToConstellationMessage::WebDriverCommand(cmd_msg)) @@ -957,8 +996,7 @@ impl Handler { let (sender, receiver) = ipc::channel().unwrap(); let session = self.session().unwrap(); - // Step 2. (TODO) If session's current top-level browsing context is no longer open, - // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(session.webview_id)?; let cmd_msg = WebDriverCommandMsg::NewWebView( session.webview_id, @@ -1505,6 +1543,9 @@ impl Handler { &mut self, parameters: ActionsParameters, ) -> WebDriverResult { + // Step 1. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(self.session()?.browsing_context_id)?; // Step 5. Let actions by tick be the result of trying to extract an action sequence let actions_by_tick = self.extract_an_action_sequence(parameters); @@ -1520,6 +1561,9 @@ impl Handler { // TODO: The previous implementation of this function was different from the spec. // Need to re-implement this to match the spec. let session = self.session()?; + // Step 1. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(session.browsing_context_id)?; session.input_state_table.borrow_mut().clear(); Ok(WebDriverResponse::Void) @@ -1639,7 +1683,9 @@ impl Handler { keys: &SendKeysParameters, ) -> WebDriverResult { let browsing_context_id = self.session()?.browsing_context_id; - + // Step 3. If session's current browsing context is no longer open, + // return error with error code no such window. + self.verify_browsing_context_is_open(browsing_context_id)?; let (sender, receiver) = ipc::channel().unwrap(); let cmd = WebDriverScriptCommand::WillSendKeys( @@ -1759,6 +1805,9 @@ impl Handler { } fn take_screenshot(&self, rect: Option>) -> WebDriverResult { + // Step 1. If session's current top-level browsing context is no longer open, + // return error with error code no such window. + self.verify_top_level_browsing_context_is_open(self.session()?.webview_id)?; let mut img = None; let interval = 1000; @@ -1906,6 +1955,46 @@ impl Handler { serde_json::to_value(map)?, ))) } + + fn verify_top_level_browsing_context_is_open( + &self, + webview_id: WebViewId, + ) -> Result<(), WebDriverError> { + let (sender, receiver) = ipc::channel().unwrap(); + self.constellation_chan + .send(EmbedderToConstellationMessage::WebDriverCommand( + WebDriverCommandMsg::IsWebViewOpen(webview_id, sender), + )) + .unwrap(); + if !receiver.recv().unwrap_or(false) { + Err(WebDriverError::new( + ErrorStatus::NoSuchWindow, + "No such window", + )) + } else { + Ok(()) + } + } + + fn verify_browsing_context_is_open( + &self, + browsing_context_id: BrowsingContextId, + ) -> Result<(), WebDriverError> { + let (sender, receiver) = ipc::channel().unwrap(); + self.constellation_chan + .send(EmbedderToConstellationMessage::WebDriverCommand( + WebDriverCommandMsg::IsBrowsingContextOpen(browsing_context_id, sender), + )) + .unwrap(); + if !receiver.recv().unwrap_or(false) { + Err(WebDriverError::new( + ErrorStatus::NoSuchWindow, + "No such window", + )) + } else { + Ok(()) + } + } } impl WebDriverHandler for Handler { diff --git a/tests/wpt/meta/webdriver/tests/classic/get_window_handle/get.py.ini b/tests/wpt/meta/webdriver/tests/classic/get_window_handle/get.py.ini deleted file mode 100644 index 0fb70be2b4d..00000000000 --- a/tests/wpt/meta/webdriver/tests/classic/get_window_handle/get.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[get.py] - [test_no_top_browsing_context] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini b/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini index 3394ac22306..da692701464 100644 --- a/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/get_window_rect/get.py.ini @@ -1,6 +1,3 @@ [get.py] - [test_no_top_browsing_context] - expected: FAIL - [test_payload] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/navigate_to/navigate.py.ini b/tests/wpt/meta/webdriver/tests/classic/navigate_to/navigate.py.ini index 2464f4b2b4d..ea869614d59 100644 --- a/tests/wpt/meta/webdriver/tests/classic/navigate_to/navigate.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/navigate_to/navigate.py.ini @@ -1,7 +1,4 @@ [navigate.py] - [test_no_top_browsing_context] - expected: FAIL - [test_seen_nodes[http\]] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/new_window/new.py.ini b/tests/wpt/meta/webdriver/tests/classic/new_window/new.py.ini deleted file mode 100644 index 374e04d8c54..00000000000 --- a/tests/wpt/meta/webdriver/tests/classic/new_window/new.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[new.py] - [test_no_top_browsing_context] - expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/perform_actions/key.py.ini b/tests/wpt/meta/webdriver/tests/classic/perform_actions/key.py.ini index 0a9efbca289..58d9ffb9364 100644 --- a/tests/wpt/meta/webdriver/tests/classic/perform_actions/key.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/perform_actions/key.py.ini @@ -1,7 +1,4 @@ [key.py] - [test_no_top_browsing_context] - expected: FAIL - [test_no_browsing_context] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/perform_actions/none.py.ini b/tests/wpt/meta/webdriver/tests/classic/perform_actions/none.py.ini index 1dad7888c51..e348a54d002 100644 --- a/tests/wpt/meta/webdriver/tests/classic/perform_actions/none.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/perform_actions/none.py.ini @@ -1,6 +1,3 @@ [none.py] - [test_no_top_browsing_context] - expected: FAIL - [test_no_browsing_context] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/perform_actions/wheel.py.ini b/tests/wpt/meta/webdriver/tests/classic/perform_actions/wheel.py.ini index c8a0364b783..0eec2e693d6 100644 --- a/tests/wpt/meta/webdriver/tests/classic/perform_actions/wheel.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/perform_actions/wheel.py.ini @@ -1,10 +1,4 @@ [wheel.py] - [test_no_top_browsing_context] - expected: FAIL - - [test_no_browsing_context] - expected: FAIL - [test_scroll_not_scrollable] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/release_actions/release.py.ini b/tests/wpt/meta/webdriver/tests/classic/release_actions/release.py.ini index 7c5e73584b6..f45f8c3203c 100644 --- a/tests/wpt/meta/webdriver/tests/classic/release_actions/release.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/release_actions/release.py.ini @@ -1,6 +1,3 @@ [release.py] - [test_no_top_browsing_context] - expected: FAIL - [test_no_browsing_context] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/set_window_rect/set.py.ini b/tests/wpt/meta/webdriver/tests/classic/set_window_rect/set.py.ini index d530b687213..3cb3261e361 100644 --- a/tests/wpt/meta/webdriver/tests/classic/set_window_rect/set.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/set_window_rect/set.py.ini @@ -1,10 +1,4 @@ [set.py] - [test_no_top_browsing_context] - expected: FAIL - - [test_no_browsing_context] - expected: FAIL - [test_restore_from_fullscreen] expected: FAIL diff --git a/tests/wpt/meta/webdriver/tests/classic/take_screenshot/screenshot.py.ini b/tests/wpt/meta/webdriver/tests/classic/take_screenshot/screenshot.py.ini index f2fac7a7fa1..e092d5aebe7 100644 --- a/tests/wpt/meta/webdriver/tests/classic/take_screenshot/screenshot.py.ini +++ b/tests/wpt/meta/webdriver/tests/classic/take_screenshot/screenshot.py.ini @@ -1,6 +1,3 @@ [screenshot.py] - [test_no_top_browsing_context] - expected: FAIL - [test_no_browsing_context] expected: FAIL