root/content/child/npapi/webplugin_delegate_impl.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Create
  2. PluginDestroyed
  3. Initialize
  4. DestroyInstance
  5. UpdateGeometry
  6. SetFocus
  7. SetPluginHasFocus
  8. SetContentAreaHasFocus
  9. GetPluginScriptableObject
  10. GetPluginNPP
  11. GetFormValue
  12. DidFinishLoadWithReason
  13. GetProcessId
  14. SendJavaScriptStream
  15. DidReceiveManualResponse
  16. DidReceiveManualData
  17. DidFinishManualLoading
  18. DidManualLoadFail
  19. GetPluginPath
  20. WindowedUpdateGeometry
  21. HandleInputEvent
  22. IsUserGesture
  23. CreateResourceClient
  24. CreateSeekableResourceClient
  25. FetchURL

// 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 "content/child/npapi/webplugin_delegate_impl.h"

#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/npapi/plugin_instance.h"
#include "content/child/npapi/plugin_lib.h"
#include "content/child/npapi/plugin_stream_url.h"
#include "content/child/npapi/plugin_url_fetcher.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"

using blink::WebCursorInfo;
using blink::WebInputEvent;

namespace content {

WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
    WebPlugin* plugin,
    const base::FilePath& filename,
    const std::string& mime_type) {
  scoped_refptr<PluginLib> plugin_lib(PluginLib::CreatePluginLib(filename));
  if (plugin_lib.get() == NULL)
    return NULL;

  NPError err = plugin_lib->NP_Initialize();
  if (err != NPERR_NO_ERROR)
    return NULL;

  scoped_refptr<PluginInstance> instance(plugin_lib->CreateInstance(mime_type));
  return new WebPluginDelegateImpl(plugin, instance.get());
}

void WebPluginDelegateImpl::PluginDestroyed() {
  if (handle_event_depth_) {
    base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
  } else {
    delete this;
  }
}

bool WebPluginDelegateImpl::Initialize(
    const GURL& url,
    const std::vector<std::string>& arg_names,
    const std::vector<std::string>& arg_values,
    bool load_manually) {
  if (instance_->plugin_lib()->plugin_info().name.find(
          base::ASCIIToUTF16("QuickTime Plug-in")) != std::wstring::npos) {
    quirks_ |= PLUGIN_QUIRK_COPY_STREAM_DATA;
  }

  instance_->set_web_plugin(plugin_);
  if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) {
    PluginLib* plugin_lib = instance()->plugin_lib();
    if (plugin_lib->instance_count() > 1) {
      return false;
    }
  }

  int argc = 0;
  scoped_ptr<char*[]> argn(new char*[arg_names.size()]);
  scoped_ptr<char*[]> argv(new char*[arg_names.size()]);
  for (size_t i = 0; i < arg_names.size(); ++i) {
    if (quirks_ & PLUGIN_QUIRK_NO_WINDOWLESS &&
        LowerCaseEqualsASCII(arg_names[i], "windowlessvideo")) {
      continue;
    }
    argn[argc] = const_cast<char*>(arg_names[i].c_str());
    argv[argc] = const_cast<char*>(arg_values[i].c_str());
    argc++;
  }

  creation_succeeded_ = instance_->Start(
      url, argn.get(), argv.get(), argc, load_manually);
  if (!creation_succeeded_) {
    VLOG(1) << "Couldn't start plug-in instance";
    return false;
  }

  windowless_ = instance_->windowless();
  if (!windowless_) {
    if (!WindowedCreatePlugin()) {
      VLOG(1) << "Couldn't create windowed plug-in";
      return false;
    }
  }

  bool should_load = PlatformInitialize();

  plugin_url_ = url.spec();

  return should_load;
}

void WebPluginDelegateImpl::DestroyInstance() {
  if (instance_.get() && (instance_->npp()->ndata != NULL)) {
    // Shutdown all streams before destroying so that
    // no streams are left "in progress".  Need to do
    // this before calling set_web_plugin(NULL) because the
    // instance uses the helper to do the download.
    instance_->CloseStreams();

    window_.window = NULL;
    if (creation_succeeded_ &&
        !(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) {
      instance_->NPP_SetWindow(&window_);
    }

    instance_->NPP_Destroy();

    instance_->set_web_plugin(NULL);

    PlatformDestroyInstance();

    instance_ = 0;
  }
}

void WebPluginDelegateImpl::UpdateGeometry(
    const gfx::Rect& window_rect,
    const gfx::Rect& clip_rect) {

  if (first_set_window_call_) {
    first_set_window_call_ = false;
    // Plugins like media player on Windows have a bug where in they handle the
    // first geometry update and ignore the rest resulting in painting issues.
    // This quirk basically ignores the first set window call sequence for
    // these plugins and has been tested for Windows plugins only.
    if (quirks_ & PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL)
      return;
  }

  if (windowless_) {
    WindowlessUpdateGeometry(window_rect, clip_rect);
  } else {
    WindowedUpdateGeometry(window_rect, clip_rect);
  }
}

void WebPluginDelegateImpl::SetFocus(bool focused) {
  DCHECK(windowless_);
  // This is called when internal WebKit focus (the focused element on the page)
  // changes, but plugins need to know about OS-level focus, so we have an extra
  // layer of focus tracking.
  //
  // On Windows, historically browsers did not set focus events to windowless
  // plugins when the toplevel window focus changes. Sending such focus events
  // breaks full screen mode in Flash because it will come out of full screen
  // mode when it loses focus, and its full screen window causes the browser to
  // lose focus.
  has_webkit_focus_ = focused;
#if !defined(OS_WIN)
  if (containing_view_has_focus_)
    SetPluginHasFocus(focused);
#else
  SetPluginHasFocus(focused);
#endif
}

void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) {
  if (focused == plugin_has_focus_)
    return;
  if (PlatformSetPluginHasFocus(focused))
    plugin_has_focus_ = focused;
}

void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) {
  containing_view_has_focus_ = has_focus;
  if (!windowless_)
    return;
#if !defined(OS_WIN)  // See SetFocus above.
  SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_);
#endif
}

NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() {
  return instance_->GetPluginScriptableObject();
}

NPP WebPluginDelegateImpl::GetPluginNPP() {
  return instance_->npp();
}

bool WebPluginDelegateImpl::GetFormValue(base::string16* value) {
  return instance_->GetFormValue(value);
}

void WebPluginDelegateImpl::DidFinishLoadWithReason(const GURL& url,
                                                    NPReason reason,
                                                    int notify_id) {
  if (quirks_ & PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS &&
      reason == NPRES_NETWORK_ERR) {
    // Flash needs this or otherwise it unloads the launching swf object.
    reason = NPRES_DONE;
  }

  instance()->DidFinishLoadWithReason(url, reason, notify_id);
}

int WebPluginDelegateImpl::GetProcessId() {
  // We are in process, so the plugin pid is this current process pid.
  return base::GetCurrentProcId();
}

void WebPluginDelegateImpl::SendJavaScriptStream(const GURL& url,
                                                 const std::string& result,
                                                 bool success,
                                                 int notify_id) {
  instance()->SendJavaScriptStream(url, result, success, notify_id);
}

void WebPluginDelegateImpl::DidReceiveManualResponse(
    const GURL& url, const std::string& mime_type,
    const std::string& headers, uint32 expected_length, uint32 last_modified) {
  if (!windowless_) {
    // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in
    // Flash.  See http://b/issue?id=892174.
    DCHECK(windowed_did_set_window_);
  }

  instance()->DidReceiveManualResponse(url, mime_type, headers,
                                       expected_length, last_modified);
}

void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer,
                                                 int length) {
  instance()->DidReceiveManualData(buffer, length);
}

void WebPluginDelegateImpl::DidFinishManualLoading() {
  instance()->DidFinishManualLoading();
}

void WebPluginDelegateImpl::DidManualLoadFail() {
  instance()->DidManualLoadFail();
}

base::FilePath WebPluginDelegateImpl::GetPluginPath() {
  return instance()->plugin_lib()->plugin_info().path;
}

void WebPluginDelegateImpl::WindowedUpdateGeometry(
    const gfx::Rect& window_rect,
    const gfx::Rect& clip_rect) {
  if (WindowedReposition(window_rect, clip_rect) ||
      !windowed_did_set_window_) {
    // Let the plugin know that it has been moved
    WindowedSetWindow();
  }
}

bool WebPluginDelegateImpl::HandleInputEvent(
    const WebInputEvent& event,
    WebCursor::CursorInfo* cursor_info) {
  DCHECK(windowless_) << "events should only be received in windowless mode";

  bool pop_user_gesture = false;
  if (IsUserGesture(event)) {
    pop_user_gesture = true;
    instance()->PushPopupsEnabledState(true);
  }

  bool handled = PlatformHandleInputEvent(event, cursor_info);

  if (pop_user_gesture) {
    instance()->PopPopupsEnabledState();
  }

  return handled;
}

bool WebPluginDelegateImpl::IsUserGesture(const WebInputEvent& event) {
  switch (event.type) {
    case WebInputEvent::MouseDown:
    case WebInputEvent::MouseUp:
    case WebInputEvent::KeyDown:
    case WebInputEvent::KeyUp:
      return true;
    default:
      return false;
  }
}

WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(
    unsigned long resource_id, const GURL& url, int notify_id) {
  return instance()->CreateStream(
      resource_id, url, std::string(), notify_id);
}

WebPluginResourceClient* WebPluginDelegateImpl::CreateSeekableResourceClient(
    unsigned long resource_id, int range_request_id) {
  WebPluginResourceClient* resource_client = instance()->GetRangeRequest(
      range_request_id);
  if (resource_client)
    resource_client->AddRangeRequestResourceId(resource_id);
  return resource_client;
}

void WebPluginDelegateImpl::FetchURL(unsigned long resource_id,
                                     int notify_id,
                                     const GURL& url,
                                     const GURL& first_party_for_cookies,
                                     const std::string& method,
                                     const char* buf,
                                     unsigned int len,
                                     const GURL& referrer,
                                     bool notify_redirects,
                                     bool is_plugin_src_load,
                                     int origin_pid,
                                     int render_frame_id,
                                     int render_view_id) {
  // TODO(jam): once we switch over to resource loading always happening in this
  // code path, remove WebPluginResourceClient abstraction.
  PluginStreamUrl* plugin_stream = instance()->CreateStream(
      resource_id, url, std::string(), notify_id);

  bool copy_stream_data = !!(quirks_ & PLUGIN_QUIRK_COPY_STREAM_DATA);
  plugin_stream->SetPluginURLFetcher(new PluginURLFetcher(
      plugin_stream, url, first_party_for_cookies, method, buf, len,
      referrer, std::string(), notify_redirects, is_plugin_src_load, origin_pid,
      render_frame_id, render_view_id, resource_id, copy_stream_data));
}

}  // namespace content

/* [<][>][^][v][top][bottom][index][help] */