Home | History | Annotate | Download | only in renderer
      1 // Copyright 2013 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 "components/plugins/renderer/mobile_youtube_plugin.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/strings/string_piece.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/values.h"
     12 #include "content/public/common/content_constants.h"
     13 #include "content/public/renderer/render_frame.h"
     14 #include "gin/handle.h"
     15 #include "gin/object_template_builder.h"
     16 #include "third_party/WebKit/public/web/WebFrame.h"
     17 #include "third_party/WebKit/public/web/WebKit.h"
     18 #include "ui/base/webui/jstemplate_builder.h"
     19 
     20 using blink::WebFrame;
     21 using blink::WebPlugin;
     22 using blink::WebURLRequest;
     23 
     24 const char* const kSlashVSlash = "/v/";
     25 const char* const kSlashESlash = "/e/";
     26 
     27 namespace {
     28 
     29 std::string GetYoutubeVideoId(const blink::WebPluginParams& params) {
     30   GURL url(params.url);
     31   std::string video_id = url.path().substr(strlen(kSlashVSlash));
     32 
     33   // Extract just the video id
     34   size_t video_id_end = video_id.find('&');
     35   if (video_id_end != std::string::npos)
     36     video_id = video_id.substr(0, video_id_end);
     37   return video_id;
     38 }
     39 
     40 std::string HtmlData(const blink::WebPluginParams& params,
     41                      base::StringPiece template_html) {
     42   base::DictionaryValue values;
     43   values.SetString("video_id", GetYoutubeVideoId(params));
     44   return webui::GetI18nTemplateHtml(template_html, &values);
     45 }
     46 
     47 bool IsValidYouTubeVideo(const std::string& path) {
     48   unsigned len = strlen(kSlashVSlash);
     49 
     50   // check for more than just /v/ or /e/.
     51   if (path.length() <= len)
     52     return false;
     53 
     54   std::string str = base::StringToLowerASCII(path);
     55   // Youtube flash url can start with /v/ or /e/.
     56   if (strncmp(str.data(), kSlashVSlash, len) != 0 &&
     57       strncmp(str.data(), kSlashESlash, len) != 0)
     58     return false;
     59 
     60   // Start after /v/
     61   for (unsigned i = len; i < path.length(); i++) {
     62     char c = str[i];
     63     if (isalpha(c) || isdigit(c) || c == '_' || c == '-')
     64       continue;
     65     // The url can have more parameters such as &hl=en after the video id.
     66     // Once we start seeing extra parameters we can return true.
     67     return c == '&' && i > len;
     68   }
     69   return true;
     70 }
     71 
     72 }  // namespace
     73 
     74 namespace plugins {
     75 
     76 MobileYouTubePlugin::MobileYouTubePlugin(content::RenderFrame* render_frame,
     77                                          blink::WebLocalFrame* frame,
     78                                          const blink::WebPluginParams& params,
     79                                          base::StringPiece& template_html,
     80                                          GURL placeholderDataUrl)
     81     : PluginPlaceholder(render_frame,
     82                         frame,
     83                         params,
     84                         HtmlData(params, template_html),
     85                         placeholderDataUrl) {}
     86 
     87 MobileYouTubePlugin::~MobileYouTubePlugin() {}
     88 
     89 // static
     90 bool MobileYouTubePlugin::IsYouTubeURL(const GURL& url,
     91                                        const std::string& mime_type) {
     92   std::string host = url.host();
     93   bool is_youtube = EndsWith(host, "youtube.com", true) ||
     94                     EndsWith(host, "youtube-nocookie.com", true);
     95 
     96   return is_youtube && IsValidYouTubeVideo(url.path()) &&
     97          LowerCaseEqualsASCII(mime_type, content::kFlashPluginSwfMimeType);
     98 }
     99 
    100 void MobileYouTubePlugin::OpenYoutubeUrlCallback() {
    101   std::string youtube("vnd.youtube:");
    102   GURL url(youtube.append(GetYoutubeVideoId(GetPluginParams())));
    103   WebURLRequest request;
    104   request.initialize();
    105   request.setURL(url);
    106   render_frame()->LoadURLExternally(
    107       GetFrame(), request, blink::WebNavigationPolicyNewForegroundTab);
    108 }
    109 
    110 void MobileYouTubePlugin::BindWebFrame(WebFrame* frame) {
    111   v8::Isolate* isolate = blink::mainThreadIsolate();
    112   v8::HandleScope handle_scope(isolate);
    113   v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
    114   DCHECK(!context.IsEmpty());
    115 
    116   v8::Context::Scope context_scope(context);
    117   v8::Handle<v8::Object> global = context->Global();
    118   global->Set(gin::StringToV8(isolate, "plugin"),
    119               gin::CreateHandle(isolate, this).ToV8());
    120 }
    121 
    122 gin::ObjectTemplateBuilder MobileYouTubePlugin::GetObjectTemplateBuilder(
    123     v8::Isolate* isolate) {
    124   return PluginPlaceholder::GetObjectTemplateBuilder(isolate)
    125     .SetMethod("openYoutubeURL", &MobileYouTubePlugin::OpenYoutubeUrlCallback);
    126 }
    127 
    128 }  // namespace plugins
    129