Commit 80143f5e authored by Gyuyoung Kim's avatar Gyuyoung Kim Committed by Commit Bot

Support to suspend/resume active page tasks of blink in the content layer

This CL introduces new APIs to suspend/resume the active tasks on the page
of blink. Android webview, devtools, or other projects which use the content
module needs to be able to suspend current active tasks including active javascript,
active timers, defer loadings, and so on. This CL supports to suspend/resume through
the APIs when they want to pause current active tasks. This feature will help us to
save CPU resources, and so on. Besides WebKit2 has been supporting this APIs for
applications which uses WebKitWebView.

TEST: WebContentsImplBrowserTest.PausePageScheduledTasks

Bug: 822564
Change-Id: Icec0390c2dffd676a6079dd9e148feb8a3e859e1
Reviewed-on: https://chromium-review.googlesource.com/952642Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Gyuyoung Kim <gyuyoung.kim@lge.com>
Cr-Commit-Position: refs/heads/master@{#547403}
parent d11d5998
......@@ -3311,6 +3311,11 @@ InterstitialPageImpl* WebContentsImpl::GetInterstitialPage() const {
return interstitial_page_;
}
void WebContentsImpl::PausePageScheduledTasks(bool paused) {
SendPageMessage(
new PageMsg_PausePageScheduledTasks(MSG_ROUTING_NONE, paused));
}
bool WebContentsImpl::IsSavable() {
// WebKit creates Document object when MIME type is application/xhtml+xml,
// so we also support this MIME type.
......
......@@ -456,6 +456,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
void ClearFocusedElement() override;
bool IsShowingContextMenu() const override;
void SetShowingContextMenu(bool showing) override;
void PausePageScheduledTasks(bool paused) override;
#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
......
......@@ -2068,4 +2068,58 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, UpdateLoadState) {
web_contents->GetLoadStateHost());
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, PausePageScheduledTasks) {
EXPECT_TRUE(embedded_test_server()->Start());
GURL test_url = embedded_test_server()->GetURL("/pause_schedule_task.html");
NavigateToURL(shell(), test_url);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
int text_length;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&text_length));
EXPECT_GT(text_length, 0);
// Suspend blink schedule tasks.
shell()->web_contents()->PausePageScheduledTasks(true);
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&text_length));
EXPECT_GT(text_length, 0);
int next_text_length;
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&next_text_length));
EXPECT_EQ(text_length, next_text_length);
// Resume the paused blink schedule tasks.
shell()->web_contents()->PausePageScheduledTasks(false);
// We call a document.getElementById five times in order to give the
// javascript time to run with DOM again.
for (int i = 0; i < 5; i++) {
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&next_text_length));
}
EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
shell(),
"domAutomationController.send(document.getElementById('textfield')."
"value.length)",
&next_text_length));
EXPECT_GT(next_text_length, text_length);
}
} // namespace content
......@@ -46,6 +46,10 @@ IPC_MESSAGE_ROUTED2(PageMsg_SetHistoryOffsetAndLength,
IPC_MESSAGE_ROUTED1(PageMsg_AudioStateChanged, bool /* is_audio_playing */)
// Pause and unpause active tasks regarding deferLoading, active javascripts,
// timer, scheduled task through |blink::WebFrameScheduler|.
IPC_MESSAGE_ROUTED1(PageMsg_PausePageScheduledTasks, bool /* paused */)
// Sent to OOPIF renderers when the main frame's ScreenInfo changes.
IPC_MESSAGE_ROUTED1(PageMsg_UpdateScreenInfo,
content::ScreenInfo /* screen_info */)
......
......@@ -805,6 +805,20 @@ class WebContents : public PageNavigator,
// Tells the WebContents whether the context menu is showing.
virtual void SetShowingContextMenu(bool showing) = 0;
// Pause and unpause scheduled tasks in the page of blink. This function will
// suspend page loadings and all background processing like active javascript,
// and timers through |blink::Page::SetPaused|. If you want to resume the
// paused state, you have to call this function with |false| argument again.
// The function with |false| should be called after calling it with |true|. If
// not, assertion will happen.
//
// WARNING: This only pauses the activities in the particular page in the
// renderer process, but may indirectly block or break other pages when they
// wait for the common backend (e.g. storage) in the browser process.
// TODO(gyuyoung): https://crbug.com/822564 - Make this feature safer and fix
// bugs.
virtual void PausePageScheduledTasks(bool paused) = 0;
#if defined(OS_ANDROID)
CONTENT_EXPORT static WebContents* FromJavaWebContents(
const base::android::JavaRef<jobject>& jweb_contents_android);
......
......@@ -1095,6 +1095,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(PageMsg_SetHistoryOffsetAndLength,
OnSetHistoryOffsetAndLength)
IPC_MESSAGE_HANDLER(PageMsg_AudioStateChanged, OnAudioStateChanged)
IPC_MESSAGE_HANDLER(PageMsg_PausePageScheduledTasks,
OnPausePageScheduledTasks)
IPC_MESSAGE_HANDLER(PageMsg_UpdateScreenInfo, OnUpdateScreenInfo)
IPC_MESSAGE_HANDLER(PageMsg_FreezePage, OnFreezePage)
......@@ -1170,6 +1172,10 @@ void RenderViewImpl::OnAudioStateChanged(bool is_audio_playing) {
webview()->AudioStateChanged(is_audio_playing);
}
void RenderViewImpl::OnPausePageScheduledTasks(bool paused) {
webview()->PausePageScheduledTasks(paused);
}
///////////////////////////////////////////////////////////////////////////////
void RenderViewImpl::ShowCreatedPopupWidget(RenderWidget* popup_widget,
......
......@@ -531,6 +531,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget,
void OnForceRedraw(const ui::LatencyInfo& latency_info);
void OnSelectWordAroundCaret();
void OnAudioStateChanged(bool is_audio_playing);
void OnPausePageScheduledTasks(bool paused);
// Page message handlers -----------------------------------------------------
void OnUpdateWindowScreenRect(gfx::Rect window_screen_rect);
......
<!DOCTYPE html>
<html>
<body>
<input id="textfield" type="text" name="fname" value="">
<input type="submit" value="Submit">
<script type="text/javascript">
var input_text = "a";
var id = setInterval(function() {
document.getElementById("textfield").value = input_text;
input_text = input_text + "a";
}, 1);
</script>
</body>
</html>
......@@ -931,6 +931,10 @@ void WebViewImpl::AcceptLanguagesChanged() {
GetPage()->AcceptLanguagesChanged();
}
void WebViewImpl::PausePageScheduledTasks(bool paused) {
GetPage()->SetPaused(paused);
}
WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
DCHECK((event.GetType() == WebInputEvent::kRawKeyDown) ||
(event.GetType() == WebInputEvent::kKeyDown) ||
......
......@@ -212,6 +212,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
const WebPoint& location) override;
void PerformPluginAction(const WebPluginAction&, const WebPoint&) override;
void AudioStateChanged(bool is_audio_playing) override;
void PausePageScheduledTasks(bool paused) override;
WebHitTestResult HitTestResultAt(const WebPoint&) override;
WebHitTestResult HitTestResultForTap(const WebPoint&,
const WebSize&) override;
......
......@@ -240,6 +240,10 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
// are allowed to start/continue in this state, and all background processing
// is also paused.
bool Paused() const { return paused_; }
// This function is public to be used for suspending/resuming Page's tasks.
// Refer to |WebContentImpl::PausePageScheduledTasks| and
// http://crbug.com/822564 for more details.
void SetPaused(bool);
void SetPageScaleFactor(float);
float PageScaleFactor() const;
......@@ -327,9 +331,6 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
// SettingsDelegate overrides.
void SettingsChanged(SettingsDelegate::ChangeType) override;
// ScopedPagePauser helpers.
void SetPaused(bool);
// Notify |plugins_changed_observers_| that plugins have changed.
void NotifyPluginsChanged() const;
......
......@@ -448,6 +448,11 @@ class WebView : protected WebWidget {
// Sets the high media engagement bit for this webview's page.
virtual void SetHasHighMediaEngagement(bool has_high_media_engagement) = 0;
// Suspend and resume ---------------------------------------------------
// Pausing and unpausing current scheduled tasks.
virtual void PausePageScheduledTasks(bool paused) = 0;
// TODO(lfg): Remove this once the refactor of WebView/WebWidget is
// completed.
WebWidget* GetWidget() { return this; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment