| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/translate/page_translator.h" | 5 #include "chrome/renderer/translate/page_translator.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/stl_util-inl.h" | 9 #include "base/stl_util-inl.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/task.h" | 11 #include "base/task.h" |
| 12 #include "chrome/renderer/navigation_state.h" |
| 12 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" | 13 #include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" |
| 14 #include "third_party/WebKit/WebKit/chromium/public/WebDataSource.h" |
| 13 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" | 15 #include "third_party/WebKit/WebKit/chromium/public/WebElement.h" |
| 14 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" | 16 #include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" |
| 15 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h" | 17 #include "third_party/WebKit/WebKit/chromium/public/WebNode.h" |
| 16 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h" | 18 #include "third_party/WebKit/WebKit/chromium/public/WebNodeList.h" |
| 17 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" | 19 #include "third_party/WebKit/WebKit/chromium/public/WebString.h" |
| 18 | 20 |
| 19 namespace { | 21 namespace { |
| 20 | 22 |
| 21 // The following elements are not supposed to be translated. | 23 // The following elements are not supposed to be translated. |
| 22 const char* const kSkippedTags[] = { "APPLET", "AREA", "BASE", "FRAME", | 24 const char* const kSkippedTags[] = { "APPLET", "AREA", "BASE", "FRAME", |
| (...skipping 30 matching lines...) Expand all Loading... |
| 53 for (size_t i = 0; i < arraysize(kSkippedTags); ++i) | 55 for (size_t i = 0; i < arraysize(kSkippedTags); ++i) |
| 54 ignored_tags_.insert(WebKit::WebString(ASCIIToUTF16(kSkippedTags[i]))); | 56 ignored_tags_.insert(WebKit::WebString(ASCIIToUTF16(kSkippedTags[i]))); |
| 55 for (size_t i = 0; i < arraysize(kInlineTags); ++i) | 57 for (size_t i = 0; i < arraysize(kInlineTags); ++i) |
| 56 inline_tags_.insert(WebKit::WebString(ASCIIToUTF16(kInlineTags[i]))); | 58 inline_tags_.insert(WebKit::WebString(ASCIIToUTF16(kInlineTags[i]))); |
| 57 } | 59 } |
| 58 | 60 |
| 59 PageTranslator::~PageTranslator() { | 61 PageTranslator::~PageTranslator() { |
| 60 ResetPageStates(); | 62 ResetPageStates(); |
| 61 } | 63 } |
| 62 | 64 |
| 63 void PageTranslator::Translate(int page_id, | 65 void PageTranslator::TranslatePage(int page_id, |
| 64 WebKit::WebFrame* web_frame, | 66 WebKit::WebFrame* main_frame, |
| 65 std::string source_lang, | 67 std::string source_lang, |
| 66 std::string target_lang) { | 68 std::string target_lang) { |
| 67 if (page_id != page_id_) { | 69 if (page_id != page_id_) { |
| 68 // This is a new page, our states are invalid. | 70 // This is a new page, our states are invalid. |
| 69 ResetPageStates(); | 71 ResetPageStates(); |
| 70 page_id_ = page_id; | 72 page_id_ = page_id; |
| 71 secure_page_ = static_cast<GURL>(web_frame->top()->url()).SchemeIsSecure(); | 73 secure_page_ = static_cast<GURL>(main_frame->top()->url()).SchemeIsSecure(); |
| 72 } | 74 } |
| 73 if (original_language_.empty()) { | 75 if (original_language_.empty()) { |
| 74 original_language_ = source_lang; | 76 original_language_ = source_lang; |
| 75 current_language_ = source_lang; | 77 current_language_ = source_lang; |
| 76 } | 78 } |
| 77 | 79 |
| 78 if (original_language_ != current_language_) { | 80 if (original_language_ != current_language_) { |
| 79 // The page has already been translated. | 81 // The page has already been translated. |
| 80 if (target_lang == current_language_) { | 82 if (target_lang == current_language_) { |
| 81 NOTREACHED(); | 83 NOTREACHED(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 96 secure_page_, this); | 98 secure_page_, this); |
| 97 pending_translations_[work_id] = *text_nodes_iter; | 99 pending_translations_[work_id] = *text_nodes_iter; |
| 98 } | 100 } |
| 99 current_language_ = target_lang; | 101 current_language_ = target_lang; |
| 100 return; | 102 return; |
| 101 } | 103 } |
| 102 | 104 |
| 103 // We are about to start the translation process. | 105 // We are about to start the translation process. |
| 104 current_language_ = target_lang; | 106 current_language_ = target_lang; |
| 105 | 107 |
| 108 // Translate all frames contained within the main-frame. |
| 109 for (WebKit::WebFrame* frame = main_frame; |
| 110 frame; frame = frame->traverseNext(false)) { |
| 111 TranslateFrame(frame); |
| 112 } |
| 113 } |
| 114 |
| 115 void PageTranslator::TranslateFrame(WebKit::WebFrame* web_frame) { |
| 116 if (page_id_ == -1) |
| 117 return; // The page has not been translated, ignore. |
| 118 |
| 119 DCHECK(!original_language_.empty() && !current_language_.empty()); |
| 120 |
| 121 WebKit::WebDataSource* ds = web_frame->dataSource(); |
| 122 NavigationState* navigation_state = NavigationState::FromDataSource(ds); |
| 123 DCHECK(navigation_state); |
| 124 if (navigation_state->was_translated()) |
| 125 return; // This frame has already been translated, nothing to do. |
| 126 |
| 127 // If the frame has no document or an empty document, it may not have been |
| 128 // loaded yet. |
| 129 if (web_frame->document().isNull() || |
| 130 web_frame->document().childNodes().length() == 0) { |
| 131 return; |
| 132 } |
| 133 |
| 106 std::stack<NodeList*> node_list_stack; | 134 std::stack<NodeList*> node_list_stack; |
| 107 std::vector<NodeList*> text_node_lists; | 135 std::vector<NodeList*> text_node_lists; |
| 108 TraverseNode(web_frame->document(), &node_list_stack, &text_node_lists); | 136 TraverseNode(web_frame->document(), &node_list_stack, &text_node_lists); |
| 109 | 137 |
| 110 std::vector<NodeList*>::iterator iter; | 138 std::vector<NodeList*>::iterator iter; |
| 111 for (iter = text_node_lists.begin(); iter != text_node_lists.end(); ++iter) { | 139 for (iter = text_node_lists.begin(); iter != text_node_lists.end(); ++iter) { |
| 112 if ((*iter)->empty()) { | 140 if ((*iter)->empty()) { |
| 113 // Nothing to translate. | 141 // Nothing to translate. |
| 114 continue; | 142 continue; |
| 115 } | 143 } |
| 116 TextChunks* text_chunks = new TextChunks; // The text chunks to translate. | 144 TextChunks* text_chunks = new TextChunks; // The text chunks to translate. |
| 117 NodeList::iterator text_nodes_iter; | 145 NodeList::iterator text_nodes_iter; |
| 118 for (text_nodes_iter = (*iter)->begin(); | 146 for (text_nodes_iter = (*iter)->begin(); |
| 119 text_nodes_iter != (*iter)->end(); ++text_nodes_iter) { | 147 text_nodes_iter != (*iter)->end(); ++text_nodes_iter) { |
| 120 DCHECK(text_nodes_iter->isTextNode()); | 148 DCHECK(text_nodes_iter->isTextNode()); |
| 121 string16 text = static_cast<string16>(text_nodes_iter->nodeValue()); | 149 string16 text = static_cast<string16>(text_nodes_iter->nodeValue()); |
| 122 DCHECK(!ContainsOnlyWhitespace(text)); | 150 DCHECK(!ContainsOnlyWhitespace(text)); |
| 123 text_chunks->push_back(text); | 151 text_chunks->push_back(text); |
| 124 } | 152 } |
| 125 | 153 |
| 126 // Send the text for translation. | 154 // Send the text for translation. |
| 127 int work_id = | 155 int work_id = |
| 128 text_translator_->Translate(*text_chunks, source_lang, target_lang, | 156 text_translator_->Translate(*text_chunks, |
| 157 original_language_, current_language_, |
| 129 secure_page_, this); | 158 secure_page_, this); |
| 130 pending_translations_[work_id] = *iter; | 159 pending_translations_[work_id] = *iter; |
| 131 // Also store the text nodes and their original text so we can translate to | 160 // Also store the text nodes and their original text so we can translate to |
| 132 // another language if necessary. | 161 // another language if necessary. |
| 133 text_nodes_.push_back(*iter); | 162 text_nodes_.push_back(*iter); |
| 134 text_chunks_.push_back(text_chunks); | 163 text_chunks_.push_back(text_chunks); |
| 135 } | 164 } |
| 165 |
| 166 navigation_state->set_was_translated(true); |
| 136 } | 167 } |
| 137 | 168 |
| 138 void PageTranslator::NavigatedToNewPage() { | 169 void PageTranslator::MainFrameNavigated() { |
| 139 // We can drop all our states, they were related to the previous page. | 170 // We can drop all our states, they were related to the previous page. |
| 140 ResetPageStates(); | 171 ResetPageStates(); |
| 141 } | 172 } |
| 142 | 173 |
| 174 bool PageTranslator::IsPageTranslated() { |
| 175 return original_language_ != current_language_; |
| 176 } |
| 177 |
| 143 bool PageTranslator::ShouldElementBeTraversed(WebKit::WebElement element) { | 178 bool PageTranslator::ShouldElementBeTraversed(WebKit::WebElement element) { |
| 144 return ignored_tags_.find(element.tagName()) == ignored_tags_.end(); | 179 return ignored_tags_.find(element.tagName()) == ignored_tags_.end(); |
| 145 } | 180 } |
| 146 | 181 |
| 147 bool PageTranslator::IsInlineElement(WebKit::WebElement element) { | 182 bool PageTranslator::IsInlineElement(WebKit::WebElement element) { |
| 148 return inline_tags_.find(element.tagName()) != inline_tags_.end(); | 183 return inline_tags_.find(element.tagName()) != inline_tags_.end(); |
| 149 } | 184 } |
| 150 | 185 |
| 151 void PageTranslator::ClearNodeZone(int work_id) { | 186 void PageTranslator::ClearNodeZone(int work_id) { |
| 152 std::map<int, NodeList*>::iterator iter = pending_translations_.find(work_id); | 187 std::map<int, NodeList*>::iterator iter = pending_translations_.find(work_id); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 STLDeleteElements(&text_nodes_); | 282 STLDeleteElements(&text_nodes_); |
| 248 STLDeleteElements(&text_chunks_); | 283 STLDeleteElements(&text_chunks_); |
| 249 original_language_.clear(); | 284 original_language_.clear(); |
| 250 current_language_.clear(); | 285 current_language_.clear(); |
| 251 ClearPendingTranslations(); | 286 ClearPendingTranslations(); |
| 252 } | 287 } |
| 253 | 288 |
| 254 void PageTranslator::ClearPendingTranslations() { | 289 void PageTranslator::ClearPendingTranslations() { |
| 255 pending_translations_.clear(); | 290 pending_translations_.clear(); |
| 256 } | 291 } |
| OLD | NEW |