diff --git a/browser/speedreader/speedreader_browsertest.cc b/browser/speedreader/speedreader_browsertest.cc index 83e27e4b4c7..cd36185fdc0 100644 --- a/browser/speedreader/speedreader_browsertest.cc +++ b/browser/speedreader/speedreader_browsertest.cc @@ -70,16 +70,28 @@ const char kTestPageReadableOnUnreadablePath[] = "/speedreader/rewriter/pages/news_pages/abcnews.com/distilled.html"; const char kTestPageRedirect[] = "/articles/redirect_me.html"; const char kTestXml[] = "/article/rss.xml"; +const char kTestTtsSimple[] = "/speedreader/article/simple.html"; +const char kTestTtsTags[] = "/speedreader/article/tags.html"; +const char kTestTtsStructure[] = "/speedreader/article/structure.html"; class SpeedReaderBrowserTest : public InProcessBrowserTest { public: SpeedReaderBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { #if BUILDFLAG(ENABLE_AI_CHAT) - feature_list_.InitWithFeatures( - {speedreader::kSpeedreaderFeature, ai_chat::features::kAIChat}, {}); + feature_list_.InitWithFeaturesAndParameters( + {{speedreader::kSpeedreaderFeature, + { + { speedreader::kSpeedreaderTTS.name, + "true" } + }}, + { ai_chat::features::kAIChat, + { {} } }}, + {}); #else - feature_list_.InitAndEnableFeature(speedreader::kSpeedreaderFeature); + feature_list_.InitAndEnableFeatureWithParameters( + speedreader::kSpeedreaderFeature, + {{speedreader::kSpeedreaderTTS.name, "true"}}); #endif brave::RegisterPathProvider(); base::FilePath test_data_dir; @@ -749,6 +761,24 @@ IN_PROC_BROWSER_TEST_F(SpeedReaderBrowserTest, RSS) { ISOLATED_WORLD_ID_BRAVE_INTERNAL)); } +IN_PROC_BROWSER_TEST_F(SpeedReaderBrowserTest, TTS) { + ToggleSpeedreader(); + + const std::string kCheckTtsParagraphs = R"js( + document.querySelectorAll('[tts-paragraph-index]').length + )js"; + + const char* pages[] = {kTestTtsSimple, kTestTtsTags, kTestTtsStructure}; + for (const auto* page : pages) { + NavigateToPageSynchronously(page); + SCOPED_TRACE(page); + EXPECT_EQ(7, content::EvalJs(ActiveWebContents(), kCheckTtsParagraphs, + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + ISOLATED_WORLD_ID_BRAVE_INTERNAL) + .ExtractInt()); + } +} + class SpeedReaderWithDistillationServiceBrowserTest : public SpeedReaderBrowserTest { public: diff --git a/components/speedreader/resources/speedreader-desktop.js b/components/speedreader/resources/speedreader-desktop.js index 03d1e1a9f06..7a68fd722f8 100644 --- a/components/speedreader/resources/speedreader-desktop.js +++ b/components/speedreader/resources/speedreader-desktop.js @@ -49,7 +49,7 @@ const getTextContent = (element) => { if (!element) { return null } - const text = element.innerText.replace(/\n|\r +/g, ' ').trim() + const text = (element.innerText || element.wholeText).replace(/\n|\r +/g, ' ').trim() if (text.length > 0) { return text } @@ -61,26 +61,6 @@ const initTextToSpeak = () => { return } - const textTags = ['P', 'DIV', 'MAIN', 'ARTICLE', 'H1', 'H2', 'H3', 'H4', 'H5', 'STRONG', 'BLOCKQUOTE'] - - const extractParagraphs = (node) => { - let paragraphs = [] - if (!node) { - return paragraphs - } - for (const child of node.children) { - if (textTags.indexOf(child.tagName) >= 0) { - const childParagraphs = extractParagraphs(child) - if (childParagraphs.length == 0) { - paragraphs.push(child) - } else { - paragraphs = paragraphs.concat(childParagraphs) - } - } - } - return paragraphs - } - let textToSpeak = 0 const makeParagraph = (elem) => { @@ -110,7 +90,43 @@ const initTextToSpeak = () => { makeParagraph($(metaDataDivId)?.querySelector('.title')) - extractParagraphs($(contentDivId)).forEach((p) => { + // Returns true if node is a leaf of the parentNode. + const isChildOf = (node, parentNode) => { + if (!parentNode) return false + + while (node) { + if (node == parentNode) return true + node = node.parentNode + } + return false + } + + nodes = document.createNodeIterator( + $(contentDivId), + NodeFilter.SHOW_TEXT, + { acceptNode(n) { return NodeFilter.FILTER_ACCEPT } }) + + let currentParent = null; + let paragraphs = [] + while ((currentNode = nodes.nextNode())) { + if (currentNode === nodes.root || + isChildOf(currentNode, currentParent) || + !getTextContent(currentNode)) { + continue + } + currentParent = currentNode.parentNode + + // Remove all nodes that are children of the current node. + // It is only possible when a paragraph starts with text, + // in this case NodeIterator produces sequence ->

, + // but

is a parent of the , so we add

and remove + paragraphs = paragraphs.filter((p) => { + return !isChildOf(p, currentParent) + }) + paragraphs.push(currentNode.parentElement) + } + + paragraphs.forEach((p) => { if (makeParagraph(p)) { createPlayer(p) } diff --git a/components/speedreader/tts_player.cc b/components/speedreader/tts_player.cc index 1011d14289c..ca5eb90fefd 100644 --- a/components/speedreader/tts_player.cc +++ b/components/speedreader/tts_player.cc @@ -221,8 +221,7 @@ const std::string& TtsPlayer::Controller::GetParagraphToRead() { void TtsPlayer::Controller::DidStartNavigation( content::NavigationHandle* handle) { - if (!handle->IsInPrimaryMainFrame() || - handle->GetReloadType() == content::ReloadType::NONE) { + if (!handle->IsInPrimaryMainFrame() || handle->IsSameDocument()) { return; } Stop(); diff --git a/test/data/speedreader/article/simple.html b/test/data/speedreader/article/simple.html new file mode 100644 index 00000000000..44fd7fc0ce4 --- /dev/null +++ b/test/data/speedreader/article/simple.html @@ -0,0 +1,56 @@ + + + +

+

Test document title

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+
+ + \ No newline at end of file diff --git a/test/data/speedreader/article/structure.html b/test/data/speedreader/article/structure.html new file mode 100644 index 00000000000..2e0be45ffdf --- /dev/null +++ b/test/data/speedreader/article/structure.html @@ -0,0 +1,63 @@ + + + +
+
+

Test document title

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+
+
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+
+
+
+ +
+ + \ No newline at end of file diff --git a/test/data/speedreader/article/tags.html b/test/data/speedreader/article/tags.html new file mode 100644 index 00000000000..e47b55d56f7 --- /dev/null +++ b/test/data/speedreader/article/tags.html @@ -0,0 +1,56 @@ + + + +
+

Test document title

+

+ Loremipsumdolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. +

+
+ + \ No newline at end of file