OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/web_view/web_view_impl.h" | 5 #include "components/web_view/web_view_impl.h" |
6 | 6 |
| 7 #include <queue> |
| 8 |
| 9 #include "base/bind.h" |
7 #include "base/command_line.h" | 10 #include "base/command_line.h" |
8 #include "components/devtools_service/public/cpp/switches.h" | 11 #include "components/devtools_service/public/cpp/switches.h" |
9 #include "components/mus/public/cpp/scoped_view_ptr.h" | 12 #include "components/mus/public/cpp/scoped_view_ptr.h" |
10 #include "components/mus/public/cpp/view.h" | 13 #include "components/mus/public/cpp/view.h" |
11 #include "components/mus/public/cpp/view_tree_connection.h" | 14 #include "components/mus/public/cpp/view_tree_connection.h" |
12 #include "components/web_view/client_initiated_frame_connection.h" | 15 #include "components/web_view/client_initiated_frame_connection.h" |
13 #include "components/web_view/frame.h" | 16 #include "components/web_view/frame.h" |
14 #include "components/web_view/frame_connection.h" | 17 #include "components/web_view/frame_connection.h" |
15 #include "components/web_view/frame_devtools_agent.h" | 18 #include "components/web_view/frame_devtools_agent.h" |
16 #include "components/web_view/frame_tree.h" | 19 #include "components/web_view/frame_tree.h" |
(...skipping 20 matching lines...) Expand all Loading... |
37 // WebViewImpl, public: | 40 // WebViewImpl, public: |
38 | 41 |
39 WebViewImpl::WebViewImpl(mojo::ApplicationImpl* app, | 42 WebViewImpl::WebViewImpl(mojo::ApplicationImpl* app, |
40 mojom::WebViewClientPtr client, | 43 mojom::WebViewClientPtr client, |
41 mojo::InterfaceRequest<mojom::WebView> request) | 44 mojo::InterfaceRequest<mojom::WebView> request) |
42 : app_(app), | 45 : app_(app), |
43 client_(client.Pass()), | 46 client_(client.Pass()), |
44 binding_(this, request.Pass()), | 47 binding_(this, request.Pass()), |
45 root_(nullptr), | 48 root_(nullptr), |
46 content_(nullptr), | 49 content_(nullptr), |
47 navigation_controller_(this) { | 50 navigation_controller_(this), |
| 51 current_find_request_(-1) { |
48 if (EnableRemoteDebugging()) | 52 if (EnableRemoteDebugging()) |
49 devtools_agent_.reset(new FrameDevToolsAgent(app_, this)); | 53 devtools_agent_.reset(new FrameDevToolsAgent(app_, this)); |
50 OnDidNavigate(); | 54 OnDidNavigate(); |
51 } | 55 } |
52 | 56 |
53 WebViewImpl::~WebViewImpl() { | 57 WebViewImpl::~WebViewImpl() { |
54 if (content_) | 58 if (content_) |
55 content_->RemoveObserver(this); | 59 content_->RemoveObserver(this); |
56 if (root_) { | 60 if (root_) { |
57 root_->RemoveObserver(this); | 61 root_->RemoveObserver(this); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 devtools_agent_->AttachFrame(forward_agent.Pass(), &client_properties); | 95 devtools_agent_->AttachFrame(forward_agent.Pass(), &client_properties); |
92 } | 96 } |
93 | 97 |
94 mojom::FrameClient* frame_client = frame_connection->frame_client(); | 98 mojom::FrameClient* frame_client = frame_connection->frame_client(); |
95 const uint32_t content_handler_id = frame_connection->GetContentHandlerID(); | 99 const uint32_t content_handler_id = frame_connection->GetContentHandlerID(); |
96 frame_tree_.reset(new FrameTree(content_handler_id, content_, | 100 frame_tree_.reset(new FrameTree(content_handler_id, content_, |
97 view_tree_client.Pass(), this, frame_client, | 101 view_tree_client.Pass(), this, frame_client, |
98 frame_connection.Pass(), client_properties)); | 102 frame_connection.Pass(), client_properties)); |
99 } | 103 } |
100 | 104 |
| 105 std::deque<Frame*> WebViewImpl::GetAllFrames() { |
| 106 std::deque<Frame*> all_frames; |
| 107 std::queue<Frame*> frames_to_search; |
| 108 frames_to_search.push(frame_tree_->root()); |
| 109 while (!frames_to_search.empty()) { |
| 110 // TODO(erg): This is not in depth first order. I'm not actually sure how |
| 111 // blink does traversal though. |
| 112 Frame* current = frames_to_search.front(); |
| 113 frames_to_search.pop(); |
| 114 for (Frame* child : current->children()) |
| 115 frames_to_search.push(child); |
| 116 all_frames.push_back(current); |
| 117 } |
| 118 return all_frames; |
| 119 } |
| 120 |
| 121 void WebViewImpl::OnContinueFinding(int32_t request_id, |
| 122 const mojo::String& search_text, |
| 123 bool found) { |
| 124 if (!found && !pending_find_frames_.empty()) { |
| 125 // No match found, search on the next frame. |
| 126 Frame* next_frame = pending_find_frames_.front(); |
| 127 pending_find_frames_.pop_front(); |
| 128 next_frame->Find(request_id, search_text, |
| 129 base::Bind(&WebViewImpl::OnContinueFinding, |
| 130 base::Unretained(this))); |
| 131 |
| 132 // TODO(erg): This doesn't deal with wrapping around the document at the |
| 133 // end when there are multiple frames. |
| 134 return; |
| 135 } |
| 136 |
| 137 pending_find_frames_.clear(); |
| 138 |
| 139 // We either found a match or we got the final rejection. Either way, we |
| 140 // alert our caller. |
| 141 |
| 142 // If nothing is found, set result to "0 of 0", otherwise, set it to |
| 143 // "-1 of 1" to indicate that we found at least one item, but we don't know |
| 144 // yet what is active. |
| 145 int ordinal = found ? -1 : 0; // -1 here means, we might know more later. |
| 146 int match_count = found ? 1 : 0; // 1 here means possibly more coming. |
| 147 |
| 148 // If we find no matches then this will be our last status update. |
| 149 // Otherwise the scoping effort will send more results. |
| 150 bool final_status_update = !found; |
| 151 |
| 152 // Send priming messages. |
| 153 client_->ReportFindInPageSelection(request_id, ordinal); |
| 154 client_->ReportFindInPageMatchCount(request_id, |
| 155 match_count, final_status_update); |
| 156 |
| 157 // TODO(erg): This doesn't iterate in the same order as the current code |
| 158 // because we don't have the correct iteration primitives. |
| 159 std::deque<Frame*> frames = GetAllFrames(); |
| 160 for (Frame* f : frames) { |
| 161 f->CancelPendingScopingEffort(); |
| 162 |
| 163 if (found) { |
| 164 MatchData& match_data = returned_find_data_[f]; |
| 165 match_data.count = 0; |
| 166 match_data.final_update = false; |
| 167 f->ScopeStringMatches(request_id, search_text, true); |
| 168 } |
| 169 } |
| 170 } |
| 171 |
101 //////////////////////////////////////////////////////////////////////////////// | 172 //////////////////////////////////////////////////////////////////////////////// |
102 // WebViewImpl, WebView implementation: | 173 // WebViewImpl, WebView implementation: |
103 | 174 |
104 void WebViewImpl::LoadRequest(mojo::URLRequestPtr request) { | 175 void WebViewImpl::LoadRequest(mojo::URLRequestPtr request) { |
105 navigation_controller_.LoadURL(request.Pass()); | 176 navigation_controller_.LoadURL(request.Pass()); |
106 } | 177 } |
107 | 178 |
108 void WebViewImpl::GetViewTreeClient( | 179 void WebViewImpl::GetViewTreeClient( |
109 mojo::InterfaceRequest<mojo::ViewTreeClient> view_tree_client) { | 180 mojo::InterfaceRequest<mojo::ViewTreeClient> view_tree_client) { |
110 mus::ViewTreeConnection::Create(this, view_tree_client.Pass()); | 181 mus::ViewTreeConnection::Create(this, view_tree_client.Pass()); |
111 } | 182 } |
112 | 183 |
| 184 void WebViewImpl::Find(int32_t request_id, const mojo::String& search_text) { |
| 185 DCHECK(frame_tree_); |
| 186 |
| 187 // TODO(erg): While this deals with multiple frames, it does not deal with |
| 188 // going forward or backwards. To do that, we'll have to port all frame |
| 189 // traversal and focusing concepts from blink::WebFrame to mojo::Frame. |
| 190 |
| 191 // TODO(erg): This isn't great and causes flashes on character |
| 192 // entry. However, it's needed for now because the internals of TextFinder |
| 193 // still track the entire state of the blink frame tree, and if there are any |
| 194 // frames that have marked text, doing a find clears the results of all |
| 195 // frames _except_ for the first frame that it finds a result on. |
| 196 StopFinding(); |
| 197 |
| 198 // TODO(erg): This cheap method does not traverse in the order that blink |
| 199 // does. |
| 200 pending_find_frames_ = GetAllFrames(); |
| 201 |
| 202 current_find_request_ = request_id; |
| 203 returned_find_data_.clear(); |
| 204 |
| 205 // Prime the continue loop. |
| 206 OnContinueFinding(request_id, search_text, false); |
| 207 } |
| 208 |
| 209 void WebViewImpl::StopFinding() { |
| 210 DCHECK(frame_tree_); |
| 211 |
| 212 // Don't report any callbacks that we get after this. |
| 213 current_find_request_ = -1; |
| 214 |
| 215 for (Frame* f : GetAllFrames()) |
| 216 f->StopFinding(true); |
| 217 } |
| 218 |
113 void WebViewImpl::GoBack() { | 219 void WebViewImpl::GoBack() { |
114 if (!navigation_controller_.CanGoBack()) | 220 if (!navigation_controller_.CanGoBack()) |
115 return; | 221 return; |
116 navigation_controller_.GoBack(); | 222 navigation_controller_.GoBack(); |
117 } | 223 } |
118 | 224 |
119 void WebViewImpl::GoForward() { | 225 void WebViewImpl::GoForward() { |
120 if (!navigation_controller_.CanGoForward()) | 226 if (!navigation_controller_.CanGoForward()) |
121 return; | 227 return; |
122 navigation_controller_.GoForward(); | 228 navigation_controller_.GoForward(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 FrameConnection::CreateConnectionForCanNavigateFrame( | 302 FrameConnection::CreateConnectionForCanNavigateFrame( |
197 app_, target, request.Pass(), callback); | 303 app_, target, request.Pass(), callback); |
198 } | 304 } |
199 | 305 |
200 void WebViewImpl::DidStartNavigation(Frame* frame) {} | 306 void WebViewImpl::DidStartNavigation(Frame* frame) {} |
201 | 307 |
202 void WebViewImpl::DidCommitProvisionalLoad(Frame* frame) { | 308 void WebViewImpl::DidCommitProvisionalLoad(Frame* frame) { |
203 navigation_controller_.FrameDidCommitProvisionalLoad(frame); | 309 navigation_controller_.FrameDidCommitProvisionalLoad(frame); |
204 } | 310 } |
205 | 311 |
| 312 void WebViewImpl::DidDestroyFrame(Frame* frame) { |
| 313 auto it = find(pending_find_frames_.begin(), pending_find_frames_.end(), |
| 314 frame); |
| 315 if (it != pending_find_frames_.end()) |
| 316 pending_find_frames_.erase(it); |
| 317 } |
| 318 |
| 319 void WebViewImpl::OnReportFindInFrameMatchCount(int32_t request_id, |
| 320 Frame* frame, |
| 321 int32_t count, |
| 322 bool final_update) { |
| 323 if (request_id != current_find_request_) |
| 324 return; |
| 325 |
| 326 auto it = returned_find_data_.find(frame); |
| 327 if (it == returned_find_data_.end()) { |
| 328 NOTREACHED(); |
| 329 return; |
| 330 } |
| 331 |
| 332 it->second.count = count; |
| 333 it->second.final_update = final_update; |
| 334 |
| 335 int merged_count = 0; |
| 336 bool merged_final_update = true; |
| 337 for (auto const& data : returned_find_data_) { |
| 338 merged_count += data.second.count; |
| 339 merged_final_update = merged_final_update && data.second.final_update; |
| 340 } |
| 341 |
| 342 // We can now take the individual FindInFrame messages and construct a |
| 343 // FindInPage message. |
| 344 client_->ReportFindInPageMatchCount(request_id, |
| 345 merged_count, |
| 346 merged_final_update); |
| 347 } |
| 348 |
| 349 void WebViewImpl::OnReportFindInPageSelection(int32_t request_id, |
| 350 Frame* frame, |
| 351 int32_t active_match_ordinal) { |
| 352 if (request_id != current_find_request_) |
| 353 return; |
| 354 |
| 355 // TODO(erg): This is the one that's really hard. To give an accurate count |
| 356 // here, we need to have all the results for frames that are before the Frame |
| 357 // that contains the selected match so we can add their sums together. |
| 358 // |
| 359 // Thankfully, we don't have to worry about this now. Since there aren't |
| 360 // back/forward controls yet, active_match_ordinal will always be 1. |
| 361 client_->ReportFindInPageSelection(request_id, active_match_ordinal); |
| 362 } |
| 363 |
206 //////////////////////////////////////////////////////////////////////////////// | 364 //////////////////////////////////////////////////////////////////////////////// |
207 // WebViewImpl, FrameDevToolsAgentDelegate implementation: | 365 // WebViewImpl, FrameDevToolsAgentDelegate implementation: |
208 | 366 |
209 void WebViewImpl::HandlePageNavigateRequest(const GURL& url) { | 367 void WebViewImpl::HandlePageNavigateRequest(const GURL& url) { |
210 mojo::URLRequestPtr request(mojo::URLRequest::New()); | 368 mojo::URLRequestPtr request(mojo::URLRequest::New()); |
211 request->url = url.spec(); | 369 request->url = url.spec(); |
212 client_->TopLevelNavigateRequest(request.Pass()); | 370 client_->TopLevelNavigateRequest(request.Pass()); |
213 } | 371 } |
214 | 372 |
215 //////////////////////////////////////////////////////////////////////////////// | 373 //////////////////////////////////////////////////////////////////////////////// |
216 // WebViewImpl, NavigationControllerDelegate implementation: | 374 // WebViewImpl, NavigationControllerDelegate implementation: |
217 | 375 |
218 void WebViewImpl::OnNavigate(mojo::URLRequestPtr request) { | 376 void WebViewImpl::OnNavigate(mojo::URLRequestPtr request) { |
219 pending_load_.reset(new PendingWebViewLoad(this)); | 377 pending_load_.reset(new PendingWebViewLoad(this)); |
220 pending_load_->Init(request.Pass()); | 378 pending_load_->Init(request.Pass()); |
221 } | 379 } |
222 | 380 |
223 void WebViewImpl::OnDidNavigate() { | 381 void WebViewImpl::OnDidNavigate() { |
224 client_->BackForwardChanged(navigation_controller_.CanGoBack() | 382 client_->BackForwardChanged(navigation_controller_.CanGoBack() |
225 ? ButtonState::BUTTON_STATE_ENABLED | 383 ? ButtonState::BUTTON_STATE_ENABLED |
226 : ButtonState::BUTTON_STATE_DISABLED, | 384 : ButtonState::BUTTON_STATE_DISABLED, |
227 navigation_controller_.CanGoForward() | 385 navigation_controller_.CanGoForward() |
228 ? ButtonState::BUTTON_STATE_ENABLED | 386 ? ButtonState::BUTTON_STATE_ENABLED |
229 : ButtonState::BUTTON_STATE_DISABLED); | 387 : ButtonState::BUTTON_STATE_DISABLED); |
230 } | 388 } |
231 | 389 |
232 } // namespace web_view | 390 } // namespace web_view |
OLD | NEW |