| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/ui/app_list/search/answer_card/answer_card_web_contents
.h" | 5 #include "chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents
.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "base/metrics/user_metrics.h" | 8 #include "base/metrics/user_metrics.h" |
| 9 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
| 10 #include "chrome/browser/ui/browser_navigator.h" |
| 11 #include "chrome/browser/ui/browser_navigator_params.h" |
| 12 #include "content/public/browser/navigation_handle.h" |
| 13 #include "content/public/browser/page_navigator.h" |
| 10 #include "content/public/browser/render_view_host.h" | 14 #include "content/public/browser/render_view_host.h" |
| 11 #include "content/public/browser/render_widget_host.h" | 15 #include "content/public/browser/render_widget_host.h" |
| 12 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
| 13 #include "content/public/common/renderer_preferences.h" | 17 #include "content/public/common/renderer_preferences.h" |
| 18 #include "net/http/http_status_code.h" |
| 14 #include "third_party/WebKit/public/platform/WebMouseEvent.h" | 19 #include "third_party/WebKit/public/platform/WebMouseEvent.h" |
| 15 #include "ui/views/controls/webview/web_contents_set_background_color.h" | 20 #include "ui/views/controls/webview/web_contents_set_background_color.h" |
| 16 #include "ui/views/controls/webview/webview.h" | 21 #include "ui/views/controls/webview/webview.h" |
| 17 #include "ui/views/widget/widget.h" | 22 #include "ui/views/widget/widget.h" |
| 18 | 23 |
| 19 namespace app_list { | 24 namespace app_list { |
| 20 | 25 |
| 21 namespace { | 26 namespace { |
| 22 | 27 |
| 28 constexpr char kSearchAnswerHasResult[] = "SearchAnswer-HasResult"; |
| 29 constexpr char kSearchAnswerIssuedQuery[] = "SearchAnswer-IssuedQuery"; |
| 30 constexpr char kSearchAnswerTitle[] = "SearchAnswer-Title"; |
| 31 |
| 23 class SearchAnswerWebView : public views::WebView { | 32 class SearchAnswerWebView : public views::WebView { |
| 24 public: | 33 public: |
| 25 explicit SearchAnswerWebView(content::BrowserContext* browser_context) | 34 explicit SearchAnswerWebView(content::BrowserContext* browser_context) |
| 26 : WebView(browser_context) {} | 35 : WebView(browser_context) {} |
| 27 | 36 |
| 28 // views::WebView overrides: | 37 // views::WebView overrides: |
| 29 void VisibilityChanged(View* starting_from, bool is_visible) override { | 38 void VisibilityChanged(View* starting_from, bool is_visible) override { |
| 30 WebView::VisibilityChanged(starting_from, is_visible); | 39 WebView::VisibilityChanged(starting_from, is_visible); |
| 31 | 40 |
| 32 if (GetWidget() && GetWidget()->IsVisible() && IsDrawn()) { | 41 if (GetWidget() && GetWidget()->IsVisible() && IsDrawn()) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 43 | 52 |
| 44 const char* GetClassName() const override { return "SearchAnswerWebView"; } | 53 const char* GetClassName() const override { return "SearchAnswerWebView"; } |
| 45 | 54 |
| 46 private: | 55 private: |
| 47 // Time when the answer became visible to the user. | 56 // Time when the answer became visible to the user. |
| 48 base::TimeTicks shown_time_; | 57 base::TimeTicks shown_time_; |
| 49 | 58 |
| 50 DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView); | 59 DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView); |
| 51 }; | 60 }; |
| 52 | 61 |
| 62 void ParseResponseHeaders(const net::HttpResponseHeaders* headers, |
| 63 bool* has_answer_card, |
| 64 std::string* result_title, |
| 65 std::string* issued_query) { |
| 66 if (!headers) { |
| 67 LOG(ERROR) << "Failed to parse response headers: no headers"; |
| 68 return; |
| 69 } |
| 70 if (headers->response_code() != net::HTTP_OK) { |
| 71 LOG(ERROR) << "Failed to parse response headers: response code=" |
| 72 << headers->response_code(); |
| 73 return; |
| 74 } |
| 75 if (!headers->HasHeaderValue(kSearchAnswerHasResult, "true")) { |
| 76 LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerHasResult |
| 77 << " header != true"; |
| 78 return; |
| 79 } |
| 80 if (!headers->GetNormalizedHeader(kSearchAnswerTitle, result_title)) { |
| 81 LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerTitle |
| 82 << " header is not present"; |
| 83 return; |
| 84 } |
| 85 if (!headers->GetNormalizedHeader(kSearchAnswerIssuedQuery, issued_query)) { |
| 86 // TODO(749320): Make the header mandatory once the production server |
| 87 // starts serving it. |
| 88 VLOG(1) << "Warning: " << kSearchAnswerIssuedQuery |
| 89 << " header is not present"; |
| 90 } |
| 91 *has_answer_card = true; |
| 92 } |
| 93 |
| 53 } // namespace | 94 } // namespace |
| 54 | 95 |
| 55 AnswerCardWebContents::AnswerCardWebContents(Profile* profile) | 96 AnswerCardWebContents::AnswerCardWebContents(Profile* profile) |
| 56 : web_view_(base::MakeUnique<SearchAnswerWebView>(profile)), | 97 : web_view_(base::MakeUnique<SearchAnswerWebView>(profile)), |
| 57 web_contents_( | 98 web_contents_( |
| 58 content::WebContents::Create(content::WebContents::CreateParams( | 99 content::WebContents::Create(content::WebContents::CreateParams( |
| 59 profile, | 100 profile, |
| 60 content::SiteInstance::Create(profile)))), | 101 content::SiteInstance::Create(profile)))), |
| 61 mouse_event_callback_(base::Bind(&AnswerCardWebContents::HandleMouseEvent, | 102 mouse_event_callback_(base::Bind(&AnswerCardWebContents::HandleMouseEvent, |
| 62 base::Unretained(this))) { | 103 base::Unretained(this))), |
| 104 profile_(profile) { |
| 63 content::RendererPreferences* renderer_prefs = | 105 content::RendererPreferences* renderer_prefs = |
| 64 web_contents_->GetMutableRendererPrefs(); | 106 web_contents_->GetMutableRendererPrefs(); |
| 65 renderer_prefs->can_accept_load_drops = false; | 107 renderer_prefs->can_accept_load_drops = false; |
| 66 // We need the OpenURLFromTab() to get called. | 108 // We need the OpenURLFromTab() to get called. |
| 67 renderer_prefs->browser_handles_all_top_level_requests = true; | 109 renderer_prefs->browser_handles_all_top_level_requests = true; |
| 68 web_contents_->GetRenderViewHost()->SyncRendererPrefs(); | 110 web_contents_->GetRenderViewHost()->SyncRendererPrefs(); |
| 69 | 111 |
| 70 Observe(web_contents_.get()); | 112 Observe(web_contents_.get()); |
| 71 web_contents_->SetDelegate(this); | 113 web_contents_->SetDelegate(this); |
| 72 web_view_->set_owned_by_client(); | 114 web_view_->set_owned_by_client(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 delegate()->UpdatePreferredSize(pref_size); | 152 delegate()->UpdatePreferredSize(pref_size); |
| 111 web_view_->SetPreferredSize(pref_size); | 153 web_view_->SetPreferredSize(pref_size); |
| 112 } | 154 } |
| 113 | 155 |
| 114 content::WebContents* AnswerCardWebContents::OpenURLFromTab( | 156 content::WebContents* AnswerCardWebContents::OpenURLFromTab( |
| 115 content::WebContents* source, | 157 content::WebContents* source, |
| 116 const content::OpenURLParams& params) { | 158 const content::OpenURLParams& params) { |
| 117 if (!params.user_gesture) | 159 if (!params.user_gesture) |
| 118 return WebContentsDelegate::OpenURLFromTab(source, params); | 160 return WebContentsDelegate::OpenURLFromTab(source, params); |
| 119 | 161 |
| 120 return delegate()->OpenURLFromTab(params); | 162 // Open the user-clicked link in the browser taking into account the requested |
| 163 // disposition. |
| 164 chrome::NavigateParams new_tab_params(profile_, params.url, |
| 165 params.transition); |
| 166 |
| 167 new_tab_params.disposition = params.disposition; |
| 168 |
| 169 if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { |
| 170 // When the user asks to open a link as a background tab, we show an |
| 171 // activated window with the new activated tab after the user closes the |
| 172 // launcher. So it's "background" relative to the launcher itself. |
| 173 new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; |
| 174 new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW_INACTIVE; |
| 175 } |
| 176 |
| 177 chrome::Navigate(&new_tab_params); |
| 178 |
| 179 base::RecordAction(base::UserMetricsAction("SearchAnswer_OpenedUrl")); |
| 180 |
| 181 return new_tab_params.target_contents; |
| 121 } | 182 } |
| 122 | 183 |
| 123 bool AnswerCardWebContents::HandleContextMenu( | 184 bool AnswerCardWebContents::HandleContextMenu( |
| 124 const content::ContextMenuParams& params) { | 185 const content::ContextMenuParams& params) { |
| 125 // Disable showing the menu. | 186 // Disable showing the menu. |
| 126 return true; | 187 return true; |
| 127 } | 188 } |
| 128 | 189 |
| 129 void AnswerCardWebContents::DidFinishNavigation( | 190 void AnswerCardWebContents::DidFinishNavigation( |
| 130 content::NavigationHandle* navigation_handle) { | 191 content::NavigationHandle* navigation_handle) { |
| 131 delegate()->DidFinishNavigation(navigation_handle); | 192 bool has_answer_card = false; |
| 193 std::string result_title; |
| 194 std::string issued_query; |
| 195 |
| 196 const bool has_error = !navigation_handle->HasCommitted() || |
| 197 navigation_handle->IsErrorPage() || |
| 198 !navigation_handle->IsInMainFrame(); |
| 199 if (has_error) { |
| 200 LOG(ERROR) << "Failed to navigate: HasCommitted=" |
| 201 << navigation_handle->HasCommitted() |
| 202 << ", IsErrorPage=" << navigation_handle->IsErrorPage() |
| 203 << ", IsInMainFrame=" << navigation_handle->IsInMainFrame(); |
| 204 } else { |
| 205 ParseResponseHeaders(navigation_handle->GetResponseHeaders(), |
| 206 &has_answer_card, &result_title, &issued_query); |
| 207 } |
| 208 |
| 209 delegate()->DidFinishNavigation(navigation_handle->GetURL(), has_error, |
| 210 has_answer_card, result_title, issued_query); |
| 132 } | 211 } |
| 133 | 212 |
| 134 void AnswerCardWebContents::DidStopLoading() { | 213 void AnswerCardWebContents::DidStopLoading() { |
| 135 delegate()->DidStopLoading(); | 214 delegate()->DidStopLoading(); |
| 136 } | 215 } |
| 137 | 216 |
| 138 void AnswerCardWebContents::DidGetUserInteraction( | 217 void AnswerCardWebContents::DidGetUserInteraction( |
| 139 const blink::WebInputEvent::Type type) { | 218 const blink::WebInputEvent::Type type) { |
| 140 base::RecordAction(base::UserMetricsAction("SearchAnswer_UserInteraction")); | 219 base::RecordAction(base::UserMetricsAction("SearchAnswer_UserInteraction")); |
| 141 } | 220 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 | 262 |
| 184 void AnswerCardWebContents::DetachFromHost() { | 263 void AnswerCardWebContents::DetachFromHost() { |
| 185 if (!host_) | 264 if (!host_) |
| 186 return; | 265 return; |
| 187 | 266 |
| 188 host_->RemoveMouseEventCallback(mouse_event_callback_); | 267 host_->RemoveMouseEventCallback(mouse_event_callback_); |
| 189 host_ = nullptr; | 268 host_ = nullptr; |
| 190 } | 269 } |
| 191 | 270 |
| 192 } // namespace app_list | 271 } // namespace app_list |
| OLD | NEW |