Home | History | Annotate | Download | only in renderer
      1 // Copyright 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "android_webview/renderer/aw_content_renderer_client.h"
      6 
      7 #include "android_webview/common/aw_resource.h"
      8 #include "android_webview/common/render_view_messages.h"
      9 #include "android_webview/common/url_constants.h"
     10 #include "android_webview/renderer/aw_key_systems.h"
     11 #include "android_webview/renderer/aw_permission_client.h"
     12 #include "android_webview/renderer/aw_render_frame_ext.h"
     13 #include "android_webview/renderer/aw_render_view_ext.h"
     14 #include "android_webview/renderer/print_render_frame_observer.h"
     15 #include "android_webview/renderer/print_web_view_helper.h"
     16 #include "base/message_loop/message_loop.h"
     17 #include "base/strings/utf_string_conversions.h"
     18 #include "components/autofill/content/renderer/autofill_agent.h"
     19 #include "components/autofill/content/renderer/password_autofill_agent.h"
     20 #include "components/visitedlink/renderer/visitedlink_slave.h"
     21 #include "content/public/common/url_constants.h"
     22 #include "content/public/renderer/document_state.h"
     23 #include "content/public/renderer/navigation_state.h"
     24 #include "content/public/renderer/render_frame.h"
     25 #include "content/public/renderer/render_thread.h"
     26 #include "content/public/renderer/render_view.h"
     27 #include "net/base/escape.h"
     28 #include "net/base/net_errors.h"
     29 #include "third_party/WebKit/public/platform/WebString.h"
     30 #include "third_party/WebKit/public/platform/WebURL.h"
     31 #include "third_party/WebKit/public/platform/WebURLError.h"
     32 #include "third_party/WebKit/public/platform/WebURLRequest.h"
     33 #include "third_party/WebKit/public/web/WebFrame.h"
     34 #include "third_party/WebKit/public/web/WebNavigationType.h"
     35 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
     36 #include "url/gurl.h"
     37 
     38 using content::RenderThread;
     39 
     40 namespace android_webview {
     41 
     42 AwContentRendererClient::AwContentRendererClient() {
     43 }
     44 
     45 AwContentRendererClient::~AwContentRendererClient() {
     46 }
     47 
     48 void AwContentRendererClient::RenderThreadStarted() {
     49   blink::WebString content_scheme(
     50       base::ASCIIToUTF16(android_webview::kContentScheme));
     51   blink::WebSecurityPolicy::registerURLSchemeAsLocal(content_scheme);
     52 
     53   blink::WebString aw_scheme(
     54       base::ASCIIToUTF16(android_webview::kAndroidWebViewVideoPosterScheme));
     55   blink::WebSecurityPolicy::registerURLSchemeAsSecure(aw_scheme);
     56 
     57   RenderThread* thread = RenderThread::Get();
     58 
     59   aw_render_process_observer_.reset(new AwRenderProcessObserver);
     60   thread->AddObserver(aw_render_process_observer_.get());
     61 
     62   visited_link_slave_.reset(new visitedlink::VisitedLinkSlave);
     63   thread->AddObserver(visited_link_slave_.get());
     64 }
     65 
     66 bool AwContentRendererClient::HandleNavigation(
     67     content::RenderFrame* render_frame,
     68     content::DocumentState* document_state,
     69     int opener_id,
     70     blink::WebFrame* frame,
     71     const blink::WebURLRequest& request,
     72     blink::WebNavigationType type,
     73     blink::WebNavigationPolicy default_policy,
     74     bool is_redirect) {
     75 
     76   // Only GETs can be overridden.
     77   if (!request.httpMethod().equals("GET"))
     78     return false;
     79 
     80   // Any navigation from loadUrl, and goBack/Forward are considered application-
     81   // initiated and hence will not yield a shouldOverrideUrlLoading() callback.
     82   // Webview classic does not consider reload application-initiated so we
     83   // continue the same behavior.
     84   // TODO(sgurun) is_content_initiated is normally false for cross-origin
     85   // navigations but since android_webview does not swap out renderers, this
     86   // works fine. This will stop working if android_webview starts swapping out
     87   // renderers on navigation.
     88   bool application_initiated =
     89       !document_state->navigation_state()->is_content_initiated()
     90       || type == blink::WebNavigationTypeBackForward;
     91 
     92   // Don't offer application-initiated navigations unless it's a redirect.
     93   if (application_initiated && !is_redirect)
     94     return false;
     95 
     96   const GURL& gurl = request.url();
     97   // For HTTP schemes, only top-level navigations can be overridden. Similarly,
     98   // WebView Classic lets app override only top level about:blank navigations.
     99   // So we filter out non-top about:blank navigations here.
    100   if (frame->parent() &&
    101       (gurl.SchemeIs(url::kHttpScheme) || gurl.SchemeIs(url::kHttpsScheme) ||
    102        gurl.SchemeIs(url::kAboutScheme)))
    103     return false;
    104 
    105   // use NavigationInterception throttle to handle the call as that can
    106   // be deferred until after the java side has been constructed.
    107   if (opener_id != MSG_ROUTING_NONE) {
    108     return false;
    109   }
    110 
    111   bool ignore_navigation = false;
    112   base::string16 url =  request.url().string();
    113 
    114   int render_frame_id = render_frame->GetRoutingID();
    115   RenderThread::Get()->Send(new AwViewHostMsg_ShouldOverrideUrlLoading(
    116       render_frame_id, url, &ignore_navigation));
    117   return ignore_navigation;
    118 }
    119 
    120 void AwContentRendererClient::RenderFrameCreated(
    121     content::RenderFrame* render_frame) {
    122   new AwPermissionClient(render_frame);
    123   new PrintRenderFrameObserver(render_frame);
    124   new AwRenderFrameExt(render_frame);
    125 
    126   // TODO(jam): when the frame tree moves into content and parent() works at
    127   // RenderFrame construction, simplify this by just checking parent().
    128   content::RenderFrame* parent_frame =
    129       render_frame->GetRenderView()->GetMainRenderFrame();
    130   if (parent_frame && parent_frame != render_frame) {
    131     // Avoid any race conditions from having the browser's UI thread tell the IO
    132     // thread that a subframe was created.
    133     RenderThread::Get()->Send(new AwViewHostMsg_SubFrameCreated(
    134         parent_frame->GetRoutingID(), render_frame->GetRoutingID()));
    135   }
    136 }
    137 
    138 void AwContentRendererClient::RenderViewCreated(
    139     content::RenderView* render_view) {
    140   AwRenderViewExt::RenderViewCreated(render_view);
    141 
    142   new printing::PrintWebViewHelper(render_view);
    143   // TODO(sgurun) do not create a password autofill agent (change
    144   // autofill agent to store a weakptr).
    145   autofill::PasswordAutofillAgent* password_autofill_agent =
    146       new autofill::PasswordAutofillAgent(render_view);
    147   new autofill::AutofillAgent(render_view, password_autofill_agent, NULL);
    148 }
    149 
    150 bool AwContentRendererClient::HasErrorPage(int http_status_code,
    151                           std::string* error_domain) {
    152   return http_status_code >= 400;
    153 }
    154 
    155 void AwContentRendererClient::GetNavigationErrorStrings(
    156     content::RenderView* /* render_view */,
    157     blink::WebFrame* /* frame */,
    158     const blink::WebURLRequest& failed_request,
    159     const blink::WebURLError& error,
    160     std::string* error_html,
    161     base::string16* error_description) {
    162   if (error_html) {
    163     GURL error_url(failed_request.url());
    164     std::string err = base::UTF16ToUTF8(error.localizedDescription);
    165     std::string contents;
    166     if (err.empty()) {
    167       contents = AwResource::GetNoDomainPageContent();
    168     } else {
    169       contents = AwResource::GetLoadErrorPageContent();
    170       ReplaceSubstringsAfterOffset(&contents, 0, "%e", err);
    171     }
    172 
    173     ReplaceSubstringsAfterOffset(&contents, 0, "%s",
    174         net::EscapeForHTML(error_url.possibly_invalid_spec()));
    175     *error_html = contents;
    176   }
    177   if (error_description) {
    178     if (error.localizedDescription.isEmpty())
    179       *error_description = base::ASCIIToUTF16(net::ErrorToString(error.reason));
    180     else
    181       *error_description = error.localizedDescription;
    182   }
    183 }
    184 
    185 unsigned long long AwContentRendererClient::VisitedLinkHash(
    186     const char* canonical_url,
    187     size_t length) {
    188   return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
    189 }
    190 
    191 bool AwContentRendererClient::IsLinkVisited(unsigned long long link_hash) {
    192   return visited_link_slave_->IsVisited(link_hash);
    193 }
    194 
    195 void AwContentRendererClient::AddKeySystems(
    196     std::vector<content::KeySystemInfo>* key_systems) {
    197   AwAddKeySystems(key_systems);
    198 }
    199 
    200 bool AwContentRendererClient::ShouldOverridePageVisibilityState(
    201     const content::RenderFrame* render_frame,
    202     blink::WebPageVisibilityState* override_state) {
    203   // webview is always visible due to rendering requirements.
    204   *override_state = blink::WebPageVisibilityStateVisible;
    205   return true;
    206 }
    207 
    208 }  // namespace android_webview
    209