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/browser/instant/instant_controller.h" | 5 #include "chrome/browser/instant/instant_controller.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 static const int kUpdateDelayMS = 200; | 31 static const int kUpdateDelayMS = 200; |
32 | 32 |
33 // static | 33 // static |
34 InstantController::HostBlacklist* InstantController::host_blacklist_ = NULL; | 34 InstantController::HostBlacklist* InstantController::host_blacklist_ = NULL; |
35 | 35 |
36 InstantController::InstantController(Profile* profile, | 36 InstantController::InstantController(Profile* profile, |
37 InstantDelegate* delegate) | 37 InstantDelegate* delegate) |
38 : delegate_(delegate), | 38 : delegate_(delegate), |
39 tab_contents_(NULL), | 39 tab_contents_(NULL), |
40 is_active_(false), | 40 is_active_(false), |
| 41 is_displayable_(false), |
41 commit_on_mouse_up_(false), | 42 commit_on_mouse_up_(false), |
42 last_transition_type_(PageTransition::LINK), | 43 last_transition_type_(PageTransition::LINK), |
43 ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)), | 44 ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)), |
44 type_(FIRST_TYPE) { | 45 type_(FIRST_TYPE) { |
45 bool enabled = GetType(profile, &type_); | 46 bool enabled = GetType(profile, &type_); |
46 DCHECK(enabled); | 47 DCHECK(enabled); |
47 PrefService* service = profile->GetPrefs(); | 48 PrefService* service = profile->GetPrefs(); |
48 if (service) { | 49 if (service) { |
49 // kInstantWasEnabledOnce was added after instant, set it now to make sure | 50 // kInstantWasEnabledOnce was added after instant, set it now to make sure |
50 // it is correctly set. | 51 // it is correctly set. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 150 |
150 if (tab_contents != tab_contents_) | 151 if (tab_contents != tab_contents_) |
151 DestroyPreviewContents(); | 152 DestroyPreviewContents(); |
152 | 153 |
153 const GURL& url = match.destination_url; | 154 const GURL& url = match.destination_url; |
154 tab_contents_ = tab_contents; | 155 tab_contents_ = tab_contents; |
155 commit_on_mouse_up_ = false; | 156 commit_on_mouse_up_ = false; |
156 last_transition_type_ = match.transition; | 157 last_transition_type_ = match.transition; |
157 const TemplateURL* template_url = NULL; | 158 const TemplateURL* template_url = NULL; |
158 | 159 |
159 if (url.is_empty() || !url.is_valid() || | 160 if (url.is_empty() || !url.is_valid()) { |
160 !ShouldShowPreviewFor(match, &template_url)) { | 161 // Assume we were invoked with GURL() and should destroy all. |
161 DestroyPreviewContents(); | 162 DestroyPreviewContents(); |
162 return; | 163 return; |
163 } | 164 } |
164 | 165 |
| 166 if (!ShouldShowPreviewFor(match, &template_url)) { |
| 167 DestroyAndLeaveActive(); |
| 168 return; |
| 169 } |
| 170 |
165 if (!loader_manager_.get()) | 171 if (!loader_manager_.get()) |
166 loader_manager_.reset(new InstantLoaderManager(this)); | 172 loader_manager_.reset(new InstantLoaderManager(this)); |
167 | 173 |
168 if (!is_active_) | 174 if (!is_active_) { |
| 175 is_active_ = true; |
169 delegate_->PrepareForInstant(); | 176 delegate_->PrepareForInstant(); |
| 177 } |
170 | 178 |
171 TemplateURLID template_url_id = template_url ? template_url->id() : 0; | 179 TemplateURLID template_url_id = template_url ? template_url->id() : 0; |
172 // Verbatim only makes sense if the search engines supports instant. | 180 // Verbatim only makes sense if the search engines supports instant. |
173 bool real_verbatim = template_url_id ? verbatim : false; | 181 bool real_verbatim = template_url_id ? verbatim : false; |
174 | 182 |
175 if (ShouldUpdateNow(template_url_id, match.destination_url)) { | 183 if (ShouldUpdateNow(template_url_id, match.destination_url)) { |
176 UpdateLoader(template_url, match.destination_url, match.transition, | 184 UpdateLoader(template_url, match.destination_url, match.transition, |
177 user_text, real_verbatim, suggested_text); | 185 user_text, real_verbatim, suggested_text); |
178 } else { | 186 } else { |
179 ScheduleUpdate(match.destination_url); | 187 ScheduleUpdate(match.destination_url); |
(...skipping 19 matching lines...) Expand all Loading... |
199 loader_manager_->pending_loader()->SetOmniboxBounds(bounds); | 207 loader_manager_->pending_loader()->SetOmniboxBounds(bounds); |
200 } | 208 } |
201 } | 209 } |
202 | 210 |
203 void InstantController::DestroyPreviewContents() { | 211 void InstantController::DestroyPreviewContents() { |
204 if (!loader_manager_.get()) { | 212 if (!loader_manager_.get()) { |
205 // We're not showing anything, nothing to do. | 213 // We're not showing anything, nothing to do. |
206 return; | 214 return; |
207 } | 215 } |
208 | 216 |
| 217 // ReleasePreviewContents sets is_active_ to false, but we need to set it |
| 218 // beore notifying the delegate so. |
| 219 is_active_ = false; |
209 delegate_->HideInstant(); | 220 delegate_->HideInstant(); |
210 delete ReleasePreviewContents(INSTANT_COMMIT_DESTROY); | 221 delete ReleasePreviewContents(INSTANT_COMMIT_DESTROY); |
211 } | 222 } |
212 | 223 |
213 bool InstantController::IsCurrent() { | 224 bool InstantController::IsCurrent() { |
214 return loader_manager_.get() && loader_manager_->active_loader()->ready() && | 225 return loader_manager_.get() && loader_manager_->active_loader() && |
215 !update_timer_.IsRunning(); | 226 loader_manager_->active_loader()->ready() && !update_timer_.IsRunning(); |
216 } | 227 } |
217 | 228 |
218 void InstantController::CommitCurrentPreview(InstantCommitType type) { | 229 void InstantController::CommitCurrentPreview(InstantCommitType type) { |
219 DCHECK(loader_manager_.get()); | 230 DCHECK(loader_manager_.get()); |
220 DCHECK(loader_manager_->current_loader()); | 231 DCHECK(loader_manager_->current_loader()); |
221 TabContentsWrapper* tab = ReleasePreviewContents(type); | 232 TabContentsWrapper* tab = ReleasePreviewContents(type); |
222 delegate_->CommitInstant(tab); | 233 delegate_->CommitInstant(tab); |
223 CompleteRelease(tab->tab_contents()); | 234 CompleteRelease(tab->tab_contents()); |
224 } | 235 } |
225 | 236 |
226 void InstantController::SetCommitOnMouseUp() { | 237 void InstantController::SetCommitOnMouseUp() { |
227 commit_on_mouse_up_ = true; | 238 commit_on_mouse_up_ = true; |
228 } | 239 } |
229 | 240 |
230 bool InstantController::IsMouseDownFromActivate() { | 241 bool InstantController::IsMouseDownFromActivate() { |
231 DCHECK(loader_manager_.get()); | 242 DCHECK(loader_manager_.get()); |
232 DCHECK(loader_manager_->current_loader()); | 243 DCHECK(loader_manager_->current_loader()); |
233 return loader_manager_->current_loader()->IsMouseDownFromActivate(); | 244 return loader_manager_->current_loader()->IsMouseDownFromActivate(); |
234 } | 245 } |
235 | 246 |
236 void InstantController::OnAutocompleteLostFocus( | 247 void InstantController::OnAutocompleteLostFocus( |
237 gfx::NativeView view_gaining_focus) { | 248 gfx::NativeView view_gaining_focus) { |
238 if (!is_active() || !GetPreviewContents()) | 249 if (!is_active() || !GetPreviewContents()) { |
| 250 DestroyPreviewContents(); |
239 return; | 251 return; |
| 252 } |
240 | 253 |
241 RenderWidgetHostView* rwhv = | 254 RenderWidgetHostView* rwhv = |
242 GetPreviewContents()->tab_contents()->GetRenderWidgetHostView(); | 255 GetPreviewContents()->tab_contents()->GetRenderWidgetHostView(); |
243 if (!view_gaining_focus || !rwhv) { | 256 if (!view_gaining_focus || !rwhv) { |
244 DestroyPreviewContents(); | 257 DestroyPreviewContents(); |
245 return; | 258 return; |
246 } | 259 } |
247 | 260 |
248 gfx::NativeView tab_view = | 261 gfx::NativeView tab_view = |
249 GetPreviewContents()->tab_contents()->GetNativeView(); | 262 GetPreviewContents()->tab_contents()->GetNativeView(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 | 308 |
296 // Loader may be null if the url blacklisted instant. | 309 // Loader may be null if the url blacklisted instant. |
297 scoped_ptr<InstantLoader> loader; | 310 scoped_ptr<InstantLoader> loader; |
298 if (loader_manager_->current_loader()) | 311 if (loader_manager_->current_loader()) |
299 loader.reset(loader_manager_->ReleaseCurrentLoader()); | 312 loader.reset(loader_manager_->ReleaseCurrentLoader()); |
300 TabContentsWrapper* tab = loader.get() ? | 313 TabContentsWrapper* tab = loader.get() ? |
301 loader->ReleasePreviewContents(type) : NULL; | 314 loader->ReleasePreviewContents(type) : NULL; |
302 | 315 |
303 ClearBlacklist(); | 316 ClearBlacklist(); |
304 is_active_ = false; | 317 is_active_ = false; |
| 318 is_displayable_ = false; |
| 319 commit_on_mouse_up_ = false; |
305 omnibox_bounds_ = gfx::Rect(); | 320 omnibox_bounds_ = gfx::Rect(); |
306 commit_on_mouse_up_ = false; | 321 loader_manager_.reset(); |
307 loader_manager_.reset(NULL); | |
308 update_timer_.Stop(); | 322 update_timer_.Stop(); |
309 return tab; | 323 return tab; |
310 } | 324 } |
311 | 325 |
312 void InstantController::CompleteRelease(TabContents* tab) { | 326 void InstantController::CompleteRelease(TabContents* tab) { |
313 tab->SetAllContentsBlocked(false); | 327 tab->SetAllContentsBlocked(false); |
314 } | 328 } |
315 | 329 |
316 TabContentsWrapper* InstantController::GetPreviewContents() { | 330 TabContentsWrapper* InstantController::GetPreviewContents() { |
317 return loader_manager_.get() ? | 331 return loader_manager_.get() && loader_manager_->current_loader() ? |
318 loader_manager_->current_loader()->preview_contents() : NULL; | 332 loader_manager_->current_loader()->preview_contents() : NULL; |
319 } | 333 } |
320 | 334 |
321 bool InstantController::IsShowingInstant() { | 335 bool InstantController::IsShowingInstant() { |
322 return loader_manager_.get() && | 336 return loader_manager_.get() && loader_manager_->current_loader() && |
323 loader_manager_->current_loader()->is_showing_instant(); | 337 loader_manager_->current_loader()->is_showing_instant(); |
324 } | 338 } |
325 | 339 |
326 bool InstantController::MightSupportInstant() { | 340 bool InstantController::MightSupportInstant() { |
327 return loader_manager_.get() && | 341 return loader_manager_.get() && loader_manager_->active_loader() && |
328 loader_manager_->active_loader()->is_showing_instant(); | 342 loader_manager_->active_loader()->is_showing_instant(); |
329 } | 343 } |
330 | 344 |
331 void InstantController::ShowInstantLoader(InstantLoader* loader) { | 345 void InstantController::ShowInstantLoader(InstantLoader* loader) { |
332 DCHECK(loader_manager_.get()); | 346 DCHECK(loader_manager_.get()); |
333 if (loader_manager_->current_loader() == loader) { | 347 if (loader_manager_->current_loader() == loader) { |
334 is_active_ = true; | 348 is_displayable_ = true; |
335 delegate_->ShowInstant(loader->preview_contents()); | 349 delegate_->ShowInstant(loader->preview_contents()); |
336 } else if (loader_manager_->pending_loader() == loader) { | 350 } else if (loader_manager_->pending_loader() == loader) { |
337 scoped_ptr<InstantLoader> old_loader; | 351 scoped_ptr<InstantLoader> old_loader; |
338 loader_manager_->MakePendingCurrent(&old_loader); | 352 loader_manager_->MakePendingCurrent(&old_loader); |
339 delegate_->ShowInstant(loader->preview_contents()); | 353 delegate_->ShowInstant(loader->preview_contents()); |
340 } else { | 354 } else { |
341 // The loader supports instant but isn't active yet. Nothing to do. | 355 // The loader supports instant but isn't active yet. Nothing to do. |
342 } | 356 } |
343 | 357 |
344 NotificationService::current()->Notify( | 358 NotificationService::current()->Notify( |
(...skipping 25 matching lines...) Expand all Loading... |
370 // revert. | 384 // revert. |
371 DestroyPreviewContents(); | 385 DestroyPreviewContents(); |
372 } | 386 } |
373 } | 387 } |
374 | 388 |
375 void InstantController::InstantLoaderDoesntSupportInstant( | 389 void InstantController::InstantLoaderDoesntSupportInstant( |
376 InstantLoader* loader) { | 390 InstantLoader* loader) { |
377 DCHECK(!loader->ready()); // We better not be showing this loader. | 391 DCHECK(!loader->ready()); // We better not be showing this loader. |
378 DCHECK(loader->template_url_id()); | 392 DCHECK(loader->template_url_id()); |
379 | 393 |
380 VLOG(1) << " provider does not support instant"; | 394 VLOG(1) << "provider does not support instant"; |
381 | 395 |
382 // Don't attempt to use instant for this search engine again. | 396 // Don't attempt to use instant for this search engine again. |
383 BlacklistFromInstant(loader->template_url_id()); | 397 BlacklistFromInstant(loader->template_url_id()); |
384 | 398 |
385 if (loader_manager_->active_loader() == loader) { | 399 if (loader_manager_->active_loader() == loader) { |
386 // The loader is active, shut down instant. | 400 // The loader is active, hide all. |
387 DestroyPreviewContents(); | 401 DestroyAndLeaveActive(); |
388 } else { | 402 } else { |
389 if (loader_manager_->current_loader() == loader && is_active_) { | 403 if (loader_manager_->current_loader() == loader && is_displayable_) { |
390 // There is a pending loader and we're active. Hide the preview. When then | 404 // There is a pending loader and we're active. Hide the preview. When then |
391 // pending loader finishes loading we'll notify the delegate to show. | 405 // pending loader finishes loading we'll notify the delegate to show. |
392 DCHECK(loader_manager_->pending_loader()); | 406 DCHECK(loader_manager_->pending_loader()); |
393 is_active_ = false; | 407 is_displayable_ = false; |
394 delegate_->HideInstant(); | 408 delegate_->HideInstant(); |
395 } | 409 } |
396 loader_manager_->DestroyLoader(loader); | 410 loader_manager_->DestroyLoader(loader); |
397 } | 411 } |
398 } | 412 } |
399 | 413 |
400 void InstantController::AddToBlacklist(InstantLoader* loader, const GURL& url) { | 414 void InstantController::AddToBlacklist(InstantLoader* loader, const GURL& url) { |
401 std::string host = url.host(); | 415 std::string host = url.host(); |
402 if (host.empty()) | 416 if (host.empty()) |
403 return; | 417 return; |
404 | 418 |
405 if (!host_blacklist_) | 419 if (!host_blacklist_) |
406 host_blacklist_ = new HostBlacklist; | 420 host_blacklist_ = new HostBlacklist; |
407 host_blacklist_->insert(host); | 421 host_blacklist_->insert(host); |
408 | 422 |
409 if (!loader_manager_.get()) | 423 if (!loader_manager_.get()) |
410 return; | 424 return; |
411 | 425 |
412 // Because of the state of the stack we can't destroy the loader now. | 426 // Because of the state of the stack we can't destroy the loader now. |
413 ScheduleDestroy(loader); | 427 ScheduleDestroy(loader); |
414 | 428 |
415 loader_manager_->ReleaseLoader(loader); | 429 loader_manager_->ReleaseLoader(loader); |
416 if (is_active_ && | 430 if (is_displayable_ && |
417 (!loader_manager_->active_loader() || | 431 (!loader_manager_->active_loader() || |
418 !loader_manager_->current_loader()->ready())) { | 432 !loader_manager_->current_loader()->ready())) { |
419 // Hide instant. When the pending loader finishes loading we'll go active | 433 // Hide instant. When the pending loader finishes loading we'll go active |
420 // again. | 434 // again. |
421 is_active_ = false; | 435 is_displayable_ = false; |
422 delegate_->HideInstant(); | 436 delegate_->HideInstant(); |
423 } | 437 } |
424 } | 438 } |
425 | 439 |
| 440 void InstantController::DestroyAndLeaveActive() { |
| 441 is_displayable_ = false; |
| 442 commit_on_mouse_up_ = false; |
| 443 delegate_->HideInstant(); |
| 444 |
| 445 loader_manager_.reset(new InstantLoaderManager(this)); |
| 446 update_timer_.Stop(); |
| 447 } |
| 448 |
| 449 TabContentsWrapper* InstantController::GetPendingPreviewContents() { |
| 450 return loader_manager_.get() && loader_manager_->pending_loader() ? |
| 451 loader_manager_->pending_loader()->preview_contents() : NULL; |
| 452 } |
| 453 |
426 bool InstantController::ShouldUpdateNow(TemplateURLID instant_id, | 454 bool InstantController::ShouldUpdateNow(TemplateURLID instant_id, |
427 const GURL& url) { | 455 const GURL& url) { |
428 DCHECK(loader_manager_.get()); | 456 DCHECK(loader_manager_.get()); |
429 | 457 |
430 if (instant_id) { | 458 if (instant_id) { |
431 // Update sites that support instant immediately, they can do their own | 459 // Update sites that support instant immediately, they can do their own |
432 // throttling. | 460 // throttling. |
433 return true; | 461 return true; |
434 } | 462 } |
435 | 463 |
436 if (url.SchemeIsFile()) | 464 if (url.SchemeIsFile()) |
437 return true; // File urls should load quickly, so don't delay loading them. | 465 return true; // File urls should load quickly, so don't delay loading them. |
438 | 466 |
439 if (loader_manager_->WillUpateChangeActiveLoader(instant_id)) { | 467 if (loader_manager_->WillUpateChangeActiveLoader(instant_id)) { |
440 // If Update would change loaders, update now. This indicates transitioning | 468 // If Update would change loaders, update now. This indicates transitioning |
441 // from an instant to non-instant loader. | 469 // from an instant to non-instant loader. |
442 return true; | 470 return true; |
443 } | 471 } |
444 | 472 |
445 InstantLoader* active_loader = loader_manager_->active_loader(); | 473 InstantLoader* active_loader = loader_manager_->active_loader(); |
446 // WillUpateChangeActiveLoader should return true if no active loader, so | 474 // WillUpateChangeActiveLoader should return true if no active loader, so |
447 // we know there will be an active loader if we get here. | 475 // we know there will be an active loader if we get here. |
448 DCHECK(active_loader); | 476 DCHECK(active_loader); |
449 // Immediately update if the hosts differ, otherwise we'll delay the update. | 477 // Immediately update if the url is the same (which should result in nothing |
450 return active_loader->url().host() != url.host(); | 478 // happening) or the hosts differ, otherwise we'll delay the update. |
| 479 return (active_loader->url() == url) || |
| 480 (active_loader->url().host() != url.host()); |
451 } | 481 } |
452 | 482 |
453 void InstantController::ScheduleUpdate(const GURL& url) { | 483 void InstantController::ScheduleUpdate(const GURL& url) { |
454 scheduled_url_ = url; | 484 scheduled_url_ = url; |
455 | 485 |
456 if (update_timer_.IsRunning()) | 486 if (update_timer_.IsRunning()) |
457 update_timer_.Stop(); | 487 update_timer_.Stop(); |
458 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateDelayMS), | 488 update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateDelayMS), |
459 this, &InstantController::ProcessScheduledUpdate); | 489 this, &InstantController::ProcessScheduledUpdate); |
460 } | 490 } |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 return "Predictive"; | 636 return "Predictive"; |
607 case VERBATIM_TYPE: | 637 case VERBATIM_TYPE: |
608 return "Verbatim"; | 638 return "Verbatim"; |
609 case PREDICTIVE_NO_AUTO_COMPLETE_TYPE: | 639 case PREDICTIVE_NO_AUTO_COMPLETE_TYPE: |
610 return "PredictiveNoAutoComplete"; | 640 return "PredictiveNoAutoComplete"; |
611 default: | 641 default: |
612 NOTREACHED(); | 642 NOTREACHED(); |
613 return std::string(); | 643 return std::string(); |
614 } | 644 } |
615 } | 645 } |
OLD | NEW |