| Index: chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
|
| diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
|
| index 34631a1282eccff99ab0e531fd8ddd06dda56a77..7f9b1dec174276c694e99e127f69181b054f1f23 100644
|
| --- a/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
|
| +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_web_contents.cc
|
| @@ -7,10 +7,15 @@
|
| #include "base/metrics/histogram_macros.h"
|
| #include "base/metrics/user_metrics.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/browser_navigator.h"
|
| +#include "chrome/browser/ui/browser_navigator_params.h"
|
| +#include "content/public/browser/navigation_handle.h"
|
| +#include "content/public/browser/page_navigator.h"
|
| #include "content/public/browser/render_view_host.h"
|
| #include "content/public/browser/render_widget_host.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "content/public/common/renderer_preferences.h"
|
| +#include "net/http/http_status_code.h"
|
| #include "third_party/WebKit/public/platform/WebMouseEvent.h"
|
| #include "ui/views/controls/webview/web_contents_set_background_color.h"
|
| #include "ui/views/controls/webview/webview.h"
|
| @@ -20,6 +25,10 @@ namespace app_list {
|
|
|
| namespace {
|
|
|
| +constexpr char kSearchAnswerHasResult[] = "SearchAnswer-HasResult";
|
| +constexpr char kSearchAnswerIssuedQuery[] = "SearchAnswer-IssuedQuery";
|
| +constexpr char kSearchAnswerTitle[] = "SearchAnswer-Title";
|
| +
|
| class SearchAnswerWebView : public views::WebView {
|
| public:
|
| explicit SearchAnswerWebView(content::BrowserContext* browser_context)
|
| @@ -50,6 +59,38 @@ class SearchAnswerWebView : public views::WebView {
|
| DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView);
|
| };
|
|
|
| +void ParseResponseHeaders(const net::HttpResponseHeaders* headers,
|
| + bool* has_answer_card,
|
| + std::string* result_title,
|
| + std::string* issued_query) {
|
| + if (!headers) {
|
| + LOG(ERROR) << "Failed to parse response headers: no headers";
|
| + return;
|
| + }
|
| + if (headers->response_code() != net::HTTP_OK) {
|
| + LOG(ERROR) << "Failed to parse response headers: response code="
|
| + << headers->response_code();
|
| + return;
|
| + }
|
| + if (!headers->HasHeaderValue(kSearchAnswerHasResult, "true")) {
|
| + LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerHasResult
|
| + << " header != true";
|
| + return;
|
| + }
|
| + if (!headers->GetNormalizedHeader(kSearchAnswerTitle, result_title)) {
|
| + LOG(ERROR) << "Failed to parse response headers: " << kSearchAnswerTitle
|
| + << " header is not present";
|
| + return;
|
| + }
|
| + if (!headers->GetNormalizedHeader(kSearchAnswerIssuedQuery, issued_query)) {
|
| + // TODO(749320): Make the header mandatory once the production server
|
| + // starts serving it.
|
| + VLOG(1) << "Warning: " << kSearchAnswerIssuedQuery
|
| + << " header is not present";
|
| + }
|
| + *has_answer_card = true;
|
| +}
|
| +
|
| } // namespace
|
|
|
| AnswerCardWebContents::AnswerCardWebContents(Profile* profile)
|
| @@ -59,7 +100,8 @@ AnswerCardWebContents::AnswerCardWebContents(Profile* profile)
|
| profile,
|
| content::SiteInstance::Create(profile)))),
|
| mouse_event_callback_(base::Bind(&AnswerCardWebContents::HandleMouseEvent,
|
| - base::Unretained(this))) {
|
| + base::Unretained(this))),
|
| + profile_(profile) {
|
| content::RendererPreferences* renderer_prefs =
|
| web_contents_->GetMutableRendererPrefs();
|
| renderer_prefs->can_accept_load_drops = false;
|
| @@ -117,7 +159,26 @@ content::WebContents* AnswerCardWebContents::OpenURLFromTab(
|
| if (!params.user_gesture)
|
| return WebContentsDelegate::OpenURLFromTab(source, params);
|
|
|
| - return delegate()->OpenURLFromTab(params);
|
| + // Open the user-clicked link in the browser taking into account the requested
|
| + // disposition.
|
| + chrome::NavigateParams new_tab_params(profile_, params.url,
|
| + params.transition);
|
| +
|
| + new_tab_params.disposition = params.disposition;
|
| +
|
| + if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) {
|
| + // When the user asks to open a link as a background tab, we show an
|
| + // activated window with the new activated tab after the user closes the
|
| + // launcher. So it's "background" relative to the launcher itself.
|
| + new_tab_params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
|
| + new_tab_params.window_action = chrome::NavigateParams::SHOW_WINDOW_INACTIVE;
|
| + }
|
| +
|
| + chrome::Navigate(&new_tab_params);
|
| +
|
| + base::RecordAction(base::UserMetricsAction("SearchAnswer_OpenedUrl"));
|
| +
|
| + return new_tab_params.target_contents;
|
| }
|
|
|
| bool AnswerCardWebContents::HandleContextMenu(
|
| @@ -128,7 +189,25 @@ bool AnswerCardWebContents::HandleContextMenu(
|
|
|
| void AnswerCardWebContents::DidFinishNavigation(
|
| content::NavigationHandle* navigation_handle) {
|
| - delegate()->DidFinishNavigation(navigation_handle);
|
| + bool has_answer_card = false;
|
| + std::string result_title;
|
| + std::string issued_query;
|
| +
|
| + const bool has_error = !navigation_handle->HasCommitted() ||
|
| + navigation_handle->IsErrorPage() ||
|
| + !navigation_handle->IsInMainFrame();
|
| + if (has_error) {
|
| + LOG(ERROR) << "Failed to navigate: HasCommitted="
|
| + << navigation_handle->HasCommitted()
|
| + << ", IsErrorPage=" << navigation_handle->IsErrorPage()
|
| + << ", IsInMainFrame=" << navigation_handle->IsInMainFrame();
|
| + } else {
|
| + ParseResponseHeaders(navigation_handle->GetResponseHeaders(),
|
| + &has_answer_card, &result_title, &issued_query);
|
| + }
|
| +
|
| + delegate()->DidFinishNavigation(navigation_handle->GetURL(), has_error,
|
| + has_answer_card, result_title, issued_query);
|
| }
|
|
|
| void AnswerCardWebContents::DidStopLoading() {
|
|
|