blob: d3aa603f0f3a0dc53c73a04a00a74be412b953a0 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/search/search_ipc_router.h"
#include <utility>
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search/search.h"
#include "chrome/common/render_messages.h"
#include "components/search/search.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace {
bool IsInInstantProcess(content::RenderFrameHost* render_frame) {
content::RenderProcessHost* process_host = render_frame->GetProcess();
const InstantService* instant_service = InstantServiceFactory::GetForProfile(
Profile::FromBrowserContext(process_host->GetBrowserContext()));
if (!instant_service)
return false;
return instant_service->IsInstantProcess(process_host->GetID());
}
class EmbeddedSearchClientFactoryImpl
: public SearchIPCRouter::EmbeddedSearchClientFactory,
public chrome::mojom::EmbeddedSearchConnector {
public:
// |web_contents| and |binding| must outlive this object.
EmbeddedSearchClientFactoryImpl(
content::WebContents* web_contents,
mojo::AssociatedBinding<chrome::mojom::EmbeddedSearch>* binding)
: client_binding_(binding), factory_bindings_(web_contents, this) {
DCHECK(web_contents);
DCHECK(binding);
// Before we are connected to a frame we throw away all messages.
mojo::MakeRequestAssociatedWithDedicatedPipe(&embedded_search_client_);
}
chrome::mojom::EmbeddedSearchClient* GetEmbeddedSearchClient() override {
return embedded_search_client_.get();
}
private:
void Connect(
chrome::mojom::EmbeddedSearchAssociatedRequest request,
chrome::mojom::EmbeddedSearchClientAssociatedPtrInfo client) override;
// An interface used to push updates to the frame that connected to us. Before
// we've been connected to a frame, messages sent on this interface go into
// the void.
chrome::mojom::EmbeddedSearchClientAssociatedPtr embedded_search_client_;
// Used to bind incoming interface requests to the implementation, which lives
// in SearchIPCRouter.
mojo::AssociatedBinding<chrome::mojom::EmbeddedSearch>* client_binding_;
// Binding used to listen to connection requests.
content::WebContentsFrameBindingSet<chrome::mojom::EmbeddedSearchConnector>
factory_bindings_;
DISALLOW_COPY_AND_ASSIGN(EmbeddedSearchClientFactoryImpl);
};
void EmbeddedSearchClientFactoryImpl::Connect(
chrome::mojom::EmbeddedSearchAssociatedRequest request,
chrome::mojom::EmbeddedSearchClientAssociatedPtrInfo client) {
content::RenderFrameHost* frame = factory_bindings_.GetCurrentTargetFrame();
const bool is_main_frame = frame->GetParent() == nullptr;
if (!IsInInstantProcess(frame) || !is_main_frame) {
return;
}
client_binding_->Bind(std::move(request));
embedded_search_client_.Bind(std::move(client));
}
} // namespace
SearchIPCRouter::SearchIPCRouter(content::WebContents* web_contents,
Delegate* delegate,
std::unique_ptr<Policy> policy)
: WebContentsObserver(web_contents),
delegate_(delegate),
policy_(std::move(policy)),
commit_counter_(0),
is_active_tab_(false),
binding_(this),
embedded_search_client_factory_(
new EmbeddedSearchClientFactoryImpl(web_contents, &binding_)) {
DCHECK(web_contents);
DCHECK(delegate);
DCHECK(policy_.get());
}
SearchIPCRouter::~SearchIPCRouter() = default;
void SearchIPCRouter::OnNavigationEntryCommitted() {
++commit_counter_;
embedded_search_client()->SetPageSequenceNumber(commit_counter_);
}
void SearchIPCRouter::SetInputInProgress(bool input_in_progress) {
if (!policy_->ShouldSendSetInputInProgress(is_active_tab_))
return;
embedded_search_client()->SetInputInProgress(input_in_progress);
}
void SearchIPCRouter::OmniboxFocusChanged(OmniboxFocusState state,
OmniboxFocusChangeReason reason) {
if (!policy_->ShouldSendOmniboxFocusChanged())
return;
embedded_search_client()->FocusChanged(state, reason);
}
void SearchIPCRouter::SendMostVisitedItems(
const std::vector<InstantMostVisitedItem>& items,
bool is_custom_links) {
if (!policy_->ShouldSendMostVisitedItems())
return;
embedded_search_client()->MostVisitedChanged(items, is_custom_links);
}
void SearchIPCRouter::SendThemeBackgroundInfo(
const ThemeBackgroundInfo& theme_info) {
if (!policy_->ShouldSendThemeBackgroundInfo())
return;
embedded_search_client()->ThemeChanged(theme_info);
}
void SearchIPCRouter::OnTabActivated() {
is_active_tab_ = true;
}
void SearchIPCRouter::OnTabDeactivated() {
is_active_tab_ = false;
}
void SearchIPCRouter::FocusOmnibox(int page_seq_no, bool focus) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessFocusOmnibox(is_active_tab_))
return;
delegate_->FocusOmnibox(focus);
}
void SearchIPCRouter::DeleteMostVisitedItem(int page_seq_no, const GURL& url) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessDeleteMostVisitedItem())
return;
delegate_->OnDeleteMostVisitedItem(url);
}
void SearchIPCRouter::UndoMostVisitedDeletion(int page_seq_no,
const GURL& url) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessUndoMostVisitedDeletion())
return;
delegate_->OnUndoMostVisitedDeletion(url);
}
void SearchIPCRouter::UndoAllMostVisitedDeletions(int page_seq_no) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessUndoAllMostVisitedDeletions())
return;
delegate_->OnUndoAllMostVisitedDeletions();
}
void SearchIPCRouter::AddCustomLink(int page_seq_no,
const GURL& url,
const std::string& title,
AddCustomLinkCallback callback) {
bool result = false;
if (page_seq_no == commit_counter_ && policy_->ShouldProcessAddCustomLink()) {
result = delegate_->OnAddCustomLink(url, title);
}
std::move(callback).Run(result);
}
void SearchIPCRouter::UpdateCustomLink(int page_seq_no,
const GURL& url,
const GURL& new_url,
const std::string& new_title,
UpdateCustomLinkCallback callback) {
bool result = false;
if (page_seq_no == commit_counter_ &&
policy_->ShouldProcessUpdateCustomLink()) {
result = delegate_->OnUpdateCustomLink(url, new_url, new_title);
}
std::move(callback).Run(result);
}
void SearchIPCRouter::DeleteCustomLink(int page_seq_no,
const GURL& url,
DeleteCustomLinkCallback callback) {
bool result = false;
if (page_seq_no == commit_counter_ &&
policy_->ShouldProcessDeleteCustomLink()) {
result = delegate_->OnDeleteCustomLink(url);
}
std::move(callback).Run(result);
}
void SearchIPCRouter::UndoCustomLinkAction(int page_seq_no) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessUndoCustomLinkAction())
return;
delegate_->OnUndoCustomLinkAction();
}
void SearchIPCRouter::ResetCustomLinks(int page_seq_no) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessResetCustomLinks())
return;
delegate_->OnResetCustomLinks();
}
void SearchIPCRouter::DoesUrlResolve(int page_seq_no,
const GURL& url,
DoesUrlResolveCallback callback) {
if (page_seq_no == commit_counter_ &&
policy_->ShouldProcessDoesUrlResolve()) {
delegate_->OnDoesUrlResolve(url, std::move(callback));
} else {
std::move(callback).Run(/*resolves=*/true, /*timeout=*/false);
}
}
void SearchIPCRouter::LogEvent(int page_seq_no,
NTPLoggingEventType event,
base::TimeDelta time) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessLogEvent())
return;
delegate_->OnLogEvent(event, time);
}
void SearchIPCRouter::LogMostVisitedImpression(
int page_seq_no,
const ntp_tiles::NTPTileImpression& impression) {
if (page_seq_no != commit_counter_)
return;
// Logging impressions is controlled by the same policy as logging events.
if (!policy_->ShouldProcessLogEvent())
return;
delegate_->OnLogMostVisitedImpression(impression);
}
void SearchIPCRouter::LogMostVisitedNavigation(
int page_seq_no,
const ntp_tiles::NTPTileImpression& impression) {
if (page_seq_no != commit_counter_)
return;
// Logging navigations is controlled by the same policy as logging events.
if (!policy_->ShouldProcessLogEvent())
return;
delegate_->OnLogMostVisitedNavigation(impression);
}
void SearchIPCRouter::PasteAndOpenDropdown(int page_seq_no,
const base::string16& text) {
if (page_seq_no != commit_counter_)
return;
if (!policy_->ShouldProcessPasteIntoOmnibox(is_active_tab_))
return;
delegate_->PasteIntoOmnibox(text);
}
void SearchIPCRouter::ChromeIdentityCheck(
int page_seq_no,
const base::string16& identity,
ChromeIdentityCheckCallback callback) {
bool result = false;
if (page_seq_no == commit_counter_ &&
policy_->ShouldProcessChromeIdentityCheck()) {
result = delegate_->ChromeIdentityCheck(identity);
}
std::move(callback).Run(result);
}
void SearchIPCRouter::HistorySyncCheck(int page_seq_no,
HistorySyncCheckCallback callback) {
bool result = false;
if (page_seq_no == commit_counter_ &&
policy_->ShouldProcessHistorySyncCheck()) {
result = delegate_->HistorySyncCheck();
}
std::move(callback).Run(result);
}
void SearchIPCRouter::SetCustomBackgroundURL(const GURL& url) {
if (!policy_->ShouldProcessSetCustomBackgroundURL())
return;
delegate_->OnSetCustomBackgroundURL(url);
}
void SearchIPCRouter::SetCustomBackgroundURLWithAttributions(
const GURL& background_url,
const std::string& attribution_line_1,
const std::string& attribution_line_2,
const GURL& action_url) {
if (!policy_->ShouldProcessSetCustomBackgroundURLWithAttributions())
return;
delegate_->OnSetCustomBackgroundURLWithAttributions(
background_url, attribution_line_1, attribution_line_2, action_url);
}
void SearchIPCRouter::SelectLocalBackgroundImage() {
if (!policy_->ShouldProcessSelectLocalBackgroundImage())
return;
delegate_->OnSelectLocalBackgroundImage();
}
void SearchIPCRouter::set_delegate_for_testing(Delegate* delegate) {
DCHECK(delegate);
delegate_ = delegate;
}
void SearchIPCRouter::set_policy_for_testing(std::unique_ptr<Policy> policy) {
DCHECK(policy);
policy_ = std::move(policy);
}