blob: 32a00885584d246c0d3910a850ec96e0c9e07e03 [file] [log] [blame]
// Copyright 2014 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/guest_view/web_view/chrome_web_view_guest_delegate.h"
#include <utility>
#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
#include "chrome/browser/favicon/favicon_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
#include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
#include "chrome/common/url_constants.h"
#include "components/browsing_data/storage_partition_http_cache_data_remover.h"
#include "components/guest_view/browser/guest_view_event.h"
#include "components/renderer_context_menu/context_menu_delegate.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/api/web_request/web_request_api.h"
#include "extensions/browser/guest_view/web_view/web_view_constants.h"
using guest_view::GuestViewEvent;
namespace extensions {
ChromeWebViewGuestDelegate::ChromeWebViewGuestDelegate(
WebViewGuest* web_view_guest)
: pending_context_menu_request_id_(0),
chromevox_injected_(false),
web_view_guest_(web_view_guest),
weak_ptr_factory_(this) {
}
ChromeWebViewGuestDelegate::~ChromeWebViewGuestDelegate() {
}
bool ChromeWebViewGuestDelegate::HandleContextMenu(
const content::ContextMenuParams& params) {
ContextMenuDelegate* menu_delegate =
ContextMenuDelegate::FromWebContents(guest_web_contents());
DCHECK(menu_delegate);
content::ContextMenuParams new_params = params;
// The only case where |context_menu_position_| is not initialized is the case
// where the input event is directly sent to the guest WebContents without
// ever going throught the embedder and BrowserPlugin's
// RenderWidgetHostViewGuest. This only happens in some tests, e.g.,
// WebViewInteractiveTest.ContextMenuParamCoordinates.
if (context_menu_position_) {
new_params.x = context_menu_position_->x();
new_params.y = context_menu_position_->y();
}
pending_menu_ = menu_delegate->BuildMenu(guest_web_contents(), new_params);
// It's possible for the returned menu to be null, so early out to avoid
// a crash. TODO(wjmaclean): find out why it's possible for this to happen
// in the first place, and if it's an error.
if (!pending_menu_)
return false;
// Pass it to embedder.
int request_id = ++pending_context_menu_request_id_;
scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
scoped_ptr<base::ListValue> items =
MenuModelToValue(pending_menu_->menu_model());
args->Set(webview::kContextMenuItems, items.release());
args->SetInteger(webview::kRequestId, request_id);
web_view_guest()->DispatchEventToView(make_scoped_ptr(
new GuestViewEvent(webview::kEventContextMenuShow, std::move(args))));
return true;
}
void ChromeWebViewGuestDelegate::OnDidInitialize() {
#if defined(OS_CHROMEOS)
chromeos::AccessibilityManager* accessibility_manager =
chromeos::AccessibilityManager::Get();
CHECK(accessibility_manager);
accessibility_subscription_ = accessibility_manager->RegisterCallback(
base::Bind(&ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged,
weak_ptr_factory_.GetWeakPtr()));
#endif
}
// static
scoped_ptr<base::ListValue> ChromeWebViewGuestDelegate::MenuModelToValue(
const ui::SimpleMenuModel& menu_model) {
scoped_ptr<base::ListValue> items(new base::ListValue());
for (int i = 0; i < menu_model.GetItemCount(); ++i) {
base::DictionaryValue* item_value = new base::DictionaryValue();
// TODO(lazyboy): We need to expose some kind of enum equivalent of
// |command_id| instead of plain integers.
item_value->SetInteger(webview::kMenuItemCommandId,
menu_model.GetCommandIdAt(i));
item_value->SetString(webview::kMenuItemLabel, menu_model.GetLabelAt(i));
items->Append(item_value);
}
return items;
}
void ChromeWebViewGuestDelegate::OnShowContextMenu(int request_id) {
if (!pending_menu_)
return;
// Make sure this was the correct request.
if (request_id != pending_context_menu_request_id_)
return;
// TODO(lazyboy): Implement.
ContextMenuDelegate* menu_delegate =
ContextMenuDelegate::FromWebContents(guest_web_contents());
menu_delegate->ShowMenu(std::move(pending_menu_));
}
bool ChromeWebViewGuestDelegate::ShouldHandleFindRequestsForEmbedder() const {
// Find requests will be handled by the guest for the Chrome signin page.
return web_view_guest_->owner_web_contents()->GetWebUI() != nullptr &&
web_view_guest_->GetOwnerSiteURL().GetOrigin().spec() ==
chrome::kChromeUIChromeSigninURL;
}
void ChromeWebViewGuestDelegate::InjectChromeVoxIfNeeded(
content::RenderViewHost* render_view_host) {
#if defined(OS_CHROMEOS)
if (!chromevox_injected_) {
chromeos::AccessibilityManager* manager =
chromeos::AccessibilityManager::Get();
if (manager && manager->IsSpokenFeedbackEnabled()) {
manager->InjectChromeVox(render_view_host);
chromevox_injected_ = true;
}
}
#endif
}
#if defined(OS_CHROMEOS)
void ChromeWebViewGuestDelegate::OnAccessibilityStatusChanged(
const chromeos::AccessibilityStatusEventDetails& details) {
if (details.notification_type == chromeos::ACCESSIBILITY_MANAGER_SHUTDOWN) {
accessibility_subscription_.reset();
} else if (details.notification_type ==
chromeos::ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK) {
if (details.enabled)
InjectChromeVoxIfNeeded(guest_web_contents()->GetRenderViewHost());
else
chromevox_injected_ = false;
}
}
#endif
void ChromeWebViewGuestDelegate::SetContextMenuPosition(
const gfx::Point& position) {
if (context_menu_position_ == nullptr)
context_menu_position_.reset(new gfx::Point());
*context_menu_position_ = position;
}
} // namespace extensions