| // Copyright 2019 The Cobalt Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "cobalt/webdriver/screenshot.h" |
| #include "base/base64.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "base/trace_event/trace_event.h" |
| #include "cobalt/webdriver/util/command_result.h" |
| |
| namespace cobalt { |
| namespace webdriver { |
| |
| namespace { |
| // Helper struct for getting a PNG screenshot synchronously. |
| struct ScreenshotResultContext { |
| ScreenshotResultContext() |
| : complete_event(base::WaitableEvent::ResetPolicy::MANUAL, |
| base::WaitableEvent::InitialState::NOT_SIGNALED) {} |
| scoped_refptr<loader::image::EncodedStaticImage> compressed_file; |
| base::WaitableEvent complete_event; |
| }; |
| |
| // Callback function to be called when PNG encoding is complete. |
| void OnPNGEncodeComplete(ScreenshotResultContext* context, |
| const scoped_refptr<loader::image::EncodedStaticImage>& |
| compressed_image_data) { |
| TRACE_EVENT0("cobalt::WebDriver", "ScreenshotHelper::onPNGEncodeComplete()"); |
| |
| DCHECK(context); |
| DCHECK(!compressed_image_data || |
| compressed_image_data->GetImageFormat() == |
| loader::image::EncodedStaticImage::ImageFormat::kPNG); |
| context->compressed_file = compressed_image_data; |
| context->complete_event.Signal(); |
| } |
| |
| } // namespace |
| |
| util::CommandResult<std::string> Screenshot::RequestScreenshot( |
| const GetScreenshotFunction& screenshot_function, |
| base::Optional<math::Rect> clip_rect) { |
| typedef util::CommandResult<std::string> CommandResult; |
| |
| // Request the screenshot and wait for the PNG data. |
| ScreenshotResultContext context; |
| screenshot_function.Run( |
| // Webdriver spec requires us to encode to PNG format. |
| loader::image::EncodedStaticImage::ImageFormat::kPNG, clip_rect, |
| base::Bind(&OnPNGEncodeComplete, base::Unretained(&context))); |
| context.complete_event.Wait(); |
| |
| uint32 file_size_in_bytes = |
| context.compressed_file |
| ? context.compressed_file->GetEstimatedSizeInBytes() |
| : 0; |
| if (file_size_in_bytes == 0 || !context.compressed_file->GetMemory()) { |
| return CommandResult(protocol::Response::kUnknownError, |
| "Failed to take screenshot."); |
| } |
| |
| // Encode the PNG data as a base64 encoded string. |
| std::string encoded; |
| { |
| // base64 encode the contents of the file to be returned to the client. |
| if (!base::Base64Encode( |
| base::StringPiece( |
| reinterpret_cast<char*>(context.compressed_file->GetMemory()), |
| file_size_in_bytes), |
| &encoded)) { |
| return CommandResult(protocol::Response::kUnknownError, |
| "Failed to base64 encode screenshot file contents."); |
| } |
| } |
| return CommandResult(encoded); |
| } |
| |
| } // namespace webdriver |
| } // namespace cobalt |