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 |