0

[iOS] Adding helper methods in PageContextWrapper

Adding helper methods in PageContextWrapper to improve readability.

Change-Id: Idb8bab08fa0a72aabc6375030d4551ddf675522f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6376283
Commit-Queue: Prasanaa Vingadassamy <prasanaa@google.com>
Reviewed-by: Nicolas MacBeth <nicolasmacbeth@google.com>
Reviewed-by: Adam Arcaro <adamta@google.com>
Cr-Commit-Position: refs/heads/main@{#1435642}
This commit is contained in:
“Prasanaa”
2025-03-20 13:19:50 -07:00
committed by Chromium LUCI CQ
parent 542e427b19
commit 3f233e5971
2 changed files with 106 additions and 88 deletions
ios/chrome/browser/intelligence

@ -105,14 +105,7 @@ void EnhancedCalendarServiceImpl::OnEnhancedCalendarResponse(
std::unique_ptr<optimization_guide::ModelQualityLogEntry> entry) {
mojom::EnhancedCalendarResponseResultPtr result_union;
if (!result.response.has_value()) {
std::string error_string =
base::StrCat({"Server model execution error: ",
service_->ResponseForErrorCode(
static_cast<int>(result.response.error().error()))});
result_union =
mojom::EnhancedCalendarResponseResult::NewError(error_string);
} else {
if (result.response.has_value()) {
std::optional<optimization_guide::proto::EnhancedCalendarResponse>
response_proto = optimization_guide::ParsedAnyMetadata<
optimization_guide::proto::EnhancedCalendarResponse>(
@ -125,6 +118,13 @@ void EnhancedCalendarServiceImpl::OnEnhancedCalendarResponse(
result_union = mojom::EnhancedCalendarResponseResult::NewError(
"Proto unmarshalling error.");
}
} else {
std::string error_string =
base::StrCat({"Server model execution error: ",
service_->ResponseForErrorCode(
static_cast<int>(result.response.error().error()))});
result_union =
mojom::EnhancedCalendarResponseResult::NewError(error_string);
}
std::move(request_callback).Run(std::move(result_union));

@ -103,90 +103,12 @@ const char16_t* kInnerTextJavaScript = u"document.body.innerText;";
// execute the `page_context_barrier` callback, otherwise the `BarrierClosure`
// will never execute its completion block.
// Retrieve WebState snapshot, if enabled.
if (_shouldGetSnapshot) {
auto callback = ^(UIImage* image) {
if ([weakSelf shouldUpdateSnapshotWithImage:image]) {
[weakSelf updateSnapshotWithBarrier:page_context_barrier];
return;
}
[weakSelf encodeImageAndSetTabScreenshot:image];
page_context_barrier.Run();
};
// If the WebState is currently visible, update the snapshot in case the
// user was scrolling, otherwise retrieve the latest version in cache or on
// disk.
if (_webState->IsVisible()) {
raw_ptr<SnapshotTabHelper> snapshot_tab_helper =
SnapshotTabHelper::FromWebState(_webState.get());
auto updateSnapshotCallback =
base::BindOnce(^(std::optional<int> result_matches) {
// TODO(crbug.com/401282824): Log the matches count to measure
// highlighting precision.
snapshot_tab_helper->UpdateSnapshotWithCallback(callback);
});
// If there is text to highlight, do it before capturing the screenshot.
if (_textToHighlight != nil) {
web::WebFrame* main_frame =
_webState->GetPageWorldWebFramesManager()->GetMainWebFrame();
web::FindInPageJavaScriptFeature* find_in_page_feature =
web::FindInPageJavaScriptFeature::GetInstance();
find_in_page_feature->Search(main_frame,
base::SysNSStringToUTF8(_textToHighlight),
std::move(updateSnapshotCallback));
} else {
std::move(updateSnapshotCallback).Run(std::nullopt);
}
} else {
SnapshotTabHelper::FromWebState(_webState.get())
->RetrieveColorSnapshot(callback);
}
[self processSnapshotWithBarrier:page_context_barrier];
}
// Get the WebState's innerText, if enabled.
if (_shouldGetInnerText) {
std::set<web::WebFrame*> web_frames =
_webState->GetPageWorldWebFramesManager()->GetAllWebFrames();
web::WebFrame* main_frame =
_webState->GetPageWorldWebFramesManager()->GetMainWebFrame();
if (web_frames.empty() || !main_frame) {
page_context_barrier.Run();
} else {
// Use a `BarrierClosure` to ensure the JavaScript is done executing in
// all WebFrames before executing the `page_context_barrier` barrier,
// which in turn signals to the PageContextWrapper that the innerText is
// done being processed. The BarrierClosure will wait until the
// `inner_text_barrier` callback is itself run once per WebFrame.
base::RepeatingClosure inner_text_barrier =
base::BarrierClosure(web_frames.size(), base::BindOnce(^{
[weakSelf webFramesInnerTextsFetchCompleted];
page_context_barrier.Run();
}));
auto callback = ^(const base::Value* value, NSError* error) {
[weakSelf parseAndConcatenateJavaScriptValue:value withError:error];
inner_text_barrier.Run();
};
// Execute the JavaScript on each WebFrame and pass in the callback (which
// executes the barrier when run).
for (web::WebFrame* web_frame : web_frames) {
// Skip WebFrames with different origins from the main WebFrame.
if (!web_frame || (!web_frame->GetSecurityOrigin().IsSameOriginWith(
main_frame->GetSecurityOrigin()))) {
inner_text_barrier.Run();
continue;
}
web_frame->ExecuteJavaScript(kInnerTextJavaScript,
base::BindOnce(callback));
}
}
[self processInnerTextWithBarrier:page_context_barrier];
}
// Create full page PDF representation of the WebState, if enabled.
@ -235,6 +157,97 @@ const char16_t* kInnerTextJavaScript = u"document.body.innerText;";
#pragma mark - Private
// Retrieve WebState snapshot. The barrier's callback will be executed for all
// codepaths in this method.
- (void)processSnapshotWithBarrier:(base::RepeatingClosure)barrier {
__weak PageContextWrapper* weakSelf = self;
auto callback = ^(UIImage* image) {
if ([weakSelf shouldUpdateSnapshotWithImage:image]) {
[weakSelf updateSnapshotWithBarrier:barrier];
return;
}
[weakSelf encodeImageAndSetTabScreenshot:image];
barrier.Run();
};
// If the WebState is currently visible, update the snapshot in case the
// user was scrolling, otherwise retrieve the latest version in cache or on
// disk.
if (_webState->IsVisible()) {
raw_ptr<SnapshotTabHelper> snapshot_tab_helper =
SnapshotTabHelper::FromWebState(_webState.get());
auto updateSnapshotCallback =
base::BindOnce(^(std::optional<int> result_matches) {
// TODO(crbug.com/401282824): Log the matches count to measure
// highlighting precision.
snapshot_tab_helper->UpdateSnapshotWithCallback(callback);
});
// If there is text to highlight, do it before capturing the screenshot.
if (_textToHighlight != nil) {
web::WebFrame* main_frame =
_webState->GetPageWorldWebFramesManager()->GetMainWebFrame();
web::FindInPageJavaScriptFeature* find_in_page_feature =
web::FindInPageJavaScriptFeature::GetInstance();
find_in_page_feature->Search(main_frame,
base::SysNSStringToUTF8(_textToHighlight),
std::move(updateSnapshotCallback));
} else {
std::move(updateSnapshotCallback).Run(std::nullopt);
}
} else {
SnapshotTabHelper::FromWebState(_webState.get())
->RetrieveColorSnapshot(callback);
}
}
// Get the WebState's innerText. The barrier's callback will be executed for all
// codepaths in this method.
- (void)processInnerTextWithBarrier:(base::RepeatingClosure)barrier {
std::set<web::WebFrame*> web_frames =
_webState->GetPageWorldWebFramesManager()->GetAllWebFrames();
web::WebFrame* main_frame =
_webState->GetPageWorldWebFramesManager()->GetMainWebFrame();
if (web_frames.empty() || !main_frame) {
barrier.Run();
return;
}
// Use a `BarrierClosure` to ensure the JavaScript is done executing in
// all WebFrames before executing the page context barrier `barrier`,
// which in turn signals to the PageContextWrapper that the innerText is
// done being processed. The BarrierClosure will wait until the
// `inner_text_barrier` callback is itself run once per WebFrame.
__weak PageContextWrapper* weakSelf = self;
base::RepeatingClosure inner_text_barrier =
base::BarrierClosure(web_frames.size(), base::BindOnce(^{
[weakSelf webFramesInnerTextsFetchCompleted];
barrier.Run();
}));
auto callback = ^(const base::Value* value, NSError* error) {
[weakSelf parseAndConcatenateJavaScriptValue:value withError:error];
inner_text_barrier.Run();
};
// Execute the JavaScript on each WebFrame and pass in the callback (which
// executes the barrier when run).
for (web::WebFrame* web_frame : web_frames) {
// Skip WebFrames with different origins from the main WebFrame.
if (!web_frame || (!web_frame->GetSecurityOrigin().IsSameOriginWith(
main_frame->GetSecurityOrigin()))) {
inner_text_barrier.Run();
continue;
}
web_frame->ExecuteJavaScript(kInnerTextJavaScript,
base::BindOnce(callback));
}
}
// All async tasks are complete, execute the overall completion callback.
// Relinquish ownership to the callback handler.
- (void)asyncWorkCompletedForPageContext {
@ -269,6 +282,11 @@ const char16_t* kInnerTextJavaScript = u"document.body.innerText;";
}
NSData* imageData = UIImagePNGRepresentation(image);
if (!imageData) {
DLOG(WARNING) << "Failed to convert the screenshot to PNG.";
return;
}
NSString* base64String = [imageData base64EncodedStringWithOptions:0];
_page_context->set_tab_screenshot(base::SysNSStringToUTF8(base64String));
}