blob: 5e3c48f7b1f183824c2b417b3e18873f1c456d2c [file] [log] [blame]
// Copyright (c) 2012 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/renderer/chrome_render_view_observer.h"
#include <stddef.h>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/debug/crash_logging.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/prerender/prerender_helper.h"
#include "chrome/renderer/web_apps.h"
#include "components/web_cache/renderer/web_cache_impl.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/window_features_converter.h"
#include "extensions/features/features.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/WebKit/public/web/WebWindowFeatures.h"
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/common/extensions/chrome_extension_messages.h"
#endif
using blink::WebFrame;
using blink::WebLocalFrame;
using blink::WebWindowFeatures;
ChromeRenderViewObserver::ChromeRenderViewObserver(
content::RenderView* render_view,
web_cache::WebCacheImpl* web_cache_impl)
: content::RenderViewObserver(render_view),
web_cache_impl_(web_cache_impl),
webview_visually_deemphasized_(false) {}
ChromeRenderViewObserver::~ChromeRenderViewObserver() {
}
bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ChromeRenderViewObserver, message)
#if !defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ChromeViewMsg_WebUIJavaScript, OnWebUIJavaScript)
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
IPC_MESSAGE_HANDLER(ChromeViewMsg_SetVisuallyDeemphasized,
OnSetVisuallyDeemphasized)
#endif
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(ChromeViewMsg_UpdateBrowserControlsState,
OnUpdateBrowserControlsState)
#endif
IPC_MESSAGE_HANDLER(ChromeViewMsg_GetWebApplicationInfo,
OnGetWebApplicationInfo)
IPC_MESSAGE_HANDLER(ChromeViewMsg_SetWindowFeatures, OnSetWindowFeatures)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
#if !defined(OS_ANDROID)
void ChromeRenderViewObserver::OnWebUIJavaScript(
const base::string16& javascript) {
webui_javascript_.push_back(javascript);
}
#endif
#if defined(OS_ANDROID)
void ChromeRenderViewObserver::OnUpdateBrowserControlsState(
content::BrowserControlsState constraints,
content::BrowserControlsState current,
bool animate) {
render_view()->UpdateBrowserControlsState(constraints, current, animate);
}
#endif
void ChromeRenderViewObserver::OnGetWebApplicationInfo() {
WebFrame* main_frame = render_view()->GetWebView()->mainFrame();
DCHECK(main_frame);
WebApplicationInfo web_app_info;
web_apps::ParseWebAppFromWebDocument(main_frame, &web_app_info);
// The warning below is specific to mobile but it doesn't hurt to show it even
// if the Chromium build is running on a desktop. It will get more exposition.
// TODO(mlamouri): Associate this message with an actual frame, to avoid the
// need to check whether or not the main frame is local.
if (web_app_info.mobile_capable == WebApplicationInfo::MOBILE_CAPABLE_APPLE &&
main_frame->isWebLocalFrame()) {
blink::WebConsoleMessage message(
blink::WebConsoleMessage::LevelWarning,
"<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"> is "
"deprecated. Please include <meta name=\"mobile-web-app-capable\" "
"content=\"yes\"> - "
"http://developers.google.com/chrome/mobile/docs/installtohomescreen");
main_frame->toWebLocalFrame()->addMessageToConsole(message);
}
// Prune out any data URLs in the set of icons. The browser process expects
// any icon with a data URL to have originated from a favicon. We don't want
// to decode arbitrary data URLs in the browser process. See
// http://b/issue?id=1162972
for (std::vector<WebApplicationInfo::IconInfo>::iterator it =
web_app_info.icons.begin(); it != web_app_info.icons.end();) {
if (it->url.SchemeIs(url::kDataScheme))
it = web_app_info.icons.erase(it);
else
++it;
}
// Truncate the strings we send to the browser process.
web_app_info.title =
web_app_info.title.substr(0, chrome::kMaxMetaTagAttributeLength);
web_app_info.description =
web_app_info.description.substr(0, chrome::kMaxMetaTagAttributeLength);
Send(new ChromeViewHostMsg_DidGetWebApplicationInfo(
routing_id(), web_app_info));
}
void ChromeRenderViewObserver::OnSetWindowFeatures(
const blink::mojom::WindowFeatures& window_features) {
render_view()->GetWebView()->setWindowFeatures(
content::ConvertMojoWindowFeaturesToWebWindowFeatures(window_features));
}
void ChromeRenderViewObserver::Navigate(const GURL& url) {
// Execute cache clear operations that were postponed until a navigation
// event (including tab reload).
if (web_cache_impl_)
web_cache_impl_->ExecutePendingClearCache();
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
void ChromeRenderViewObserver::OnSetVisuallyDeemphasized(bool deemphasized) {
if (webview_visually_deemphasized_ == deemphasized)
return;
webview_visually_deemphasized_ = deemphasized;
if (deemphasized) {
// 70% opaque grey.
SkColor greyish = SkColorSetARGB(178, 0, 0, 0);
render_view()->GetWebView()->setPageOverlayColor(greyish);
} else {
render_view()->GetWebView()->setPageOverlayColor(SK_ColorTRANSPARENT);
}
}
#endif
void ChromeRenderViewObserver::DidCommitProvisionalLoad(
blink::WebLocalFrame* frame,
bool is_new_navigation) {
auto* render_frame = content::RenderFrame::FromWebFrame(frame);
if (render_frame->IsMainFrame() &&
(render_frame->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) &&
!webui_javascript_.empty()) {
for (const auto& script : webui_javascript_)
render_view()->GetMainRenderFrame()->ExecuteJavaScript(script);
webui_javascript_.clear();
}
}
void ChromeRenderViewObserver::OnDestruct() {
delete this;
}