void PluginWidgetAndroid::scrollToVisiblePluginRect() { if (!m_hasFocus || m_requestedVisibleRect.isEmpty() || m_visibleDocRect.isEmpty()) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s call m_hasFocus=%d m_requestedVisibleRect.isEmpty()=%d" " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus, m_requestedVisibleRect.isEmpty(), m_visibleDocRect.isEmpty()); #endif return; } // if the entire rect is already visible then we don't need to scroll if (m_visibleDocRect.contains(m_requestedVisibleRect)) return; // find the center of the visibleRect in document coordinates int rectCenterX = m_requestedVisibleRect.fLeft + m_requestedVisibleRect.width()/2; int rectCenterY = m_requestedVisibleRect.fTop + m_requestedVisibleRect.height()/2; // position the corner of the visible doc to center the requested rect int scrollDocX = MAX(0, rectCenterX - (m_visibleDocRect.width()/2)); int scrollDocY = MAX(0, rectCenterY - (m_visibleDocRect.height()/2)); ScrollView* scrollView = m_pluginView->parent(); android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s call scrollTo (%d,%d) to center (%d,%d)", __FUNCTION__, scrollDocX, scrollDocY, rectCenterX, rectCenterY); #endif core->scrollTo(scrollDocX, scrollDocY, true); }
void PluginWidgetAndroid::scrollToVisiblePluginRect() { if (!m_hasFocus || m_requestedVisibleRect.isEmpty() || m_visibleDocRect.isEmpty()) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s call m_hasFocus=%d m_requestedVisibleRect.isEmpty()=%d" " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus, m_requestedVisibleRect.isEmpty(), m_visibleDocRect.isEmpty()); #endif return; } // if the entire rect is already visible then we don't need to scroll if (m_visibleDocRect.contains(m_requestedVisibleRect)) return; // find the center of the visibleRect in document coordinates int rectCenterX = m_requestedVisibleRect.fLeft + m_requestedVisibleRect.width()/2; int rectCenterY = m_requestedVisibleRect.fTop + m_requestedVisibleRect.height()/2; // find document coordinates for center of the visible screen int visibleDocCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2; int visibleDocCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2; //compute the delta of the two points and scale to screen coordinates int deltaX = rectCenterX - visibleDocCenterX; int deltaY = rectCenterY - visibleDocCenterY; ScrollView* scrollView = m_pluginView->parent(); android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY); #endif core->scrollBy(deltaX, deltaY, true); }
void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s count=%d", __FUNCTION__, count); #endif // ensure the count does not exceed our allocated space if (count > MAX_REQUESTED_RECTS) count = MAX_REQUESTED_RECTS; // store the values in member variables m_requestedVisibleRectCount = count; memcpy(m_requestedVisibleRects, rects, count * sizeof(rects[0])); #if DEBUG_VISIBLE_RECTS // FIXME: this fixes bad data from the plugin // take it out once plugin supplies better data for (int index = 0; index < count; index++) { PLUGIN_LOG("%s [%d](%d,%d,%d,%d)", __FUNCTION__, index, m_requestedVisibleRects[index].left, m_requestedVisibleRects[index].top, m_requestedVisibleRects[index].right, m_requestedVisibleRects[index].bottom); if (m_requestedVisibleRects[index].left == m_requestedVisibleRects[index].right) { m_requestedVisibleRects[index].right += 1; } if (m_requestedVisibleRects[index].top == m_requestedVisibleRects[index].bottom) { m_requestedVisibleRects[index].bottom += 1; } } #endif computeVisiblePluginRect(); }
void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s (%d,%d,%d,%d)[%f]", __FUNCTION__, visibleDocRect.left, visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom, zoom); #endif int oldScreenW = m_visibleDocRect.width(); int oldScreenH = m_visibleDocRect.height(); const bool zoomChanged = m_cachedZoomLevel != zoom; // make local copies of the parameters m_cachedZoomLevel = zoom; m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom); int newScreenW = m_visibleDocRect.width(); int newScreenH = m_visibleDocRect.height(); // if the screen dimensions have changed by more than 5 pixels in either // direction then recompute the plugin's visible rectangle if (abs(oldScreenW - newScreenW) > 5 || abs(oldScreenH - newScreenH) > 5) { PLUGIN_LOG("%s VisibleDoc old=[%d,%d] new=[%d,%d] ", __FUNCTION__, oldScreenW, oldScreenH, newScreenW, newScreenH); computeVisiblePluginRect(); } sendSizeAndVisibilityEvents(zoomChanged); }
void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s (%d,%d,%d,%d)[%f]", __FUNCTION__, visibleDocRect.left, visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom, zoom); #endif // TODO update the bitmap size based on the zoom? (for kBitmap_ANPDrawingModel) int oldScreenW = m_visibleDocRect.width(); int oldScreenH = m_visibleDocRect.height(); // make local copies of the parameters m_zoomLevel = zoom; m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom); int newScreenW = m_visibleDocRect.width(); int newScreenH = m_visibleDocRect.height(); // if the screen dimensions have changed by more than 5 pixels in either // direction then recompute the plugin's visible rectangle if (abs(oldScreenW - newScreenW) > 5 || abs(oldScreenH - newScreenH) > 5) { PLUGIN_LOG("%s VisibleDoc old=[%d,%d] new=[%d,%d] ", __FUNCTION__, oldScreenW, oldScreenH, newScreenW, newScreenH); computeVisiblePluginRect(); } bool visible = SkIRect::Intersects(m_visibleDocRect, m_pluginBounds); if(m_visible != visible) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%p changeVisiblity[%d] pluginBounds(%d,%d,%d,%d)", m_pluginView->instance(), visible, m_pluginBounds.fLeft, m_pluginBounds.fTop, m_pluginBounds.fRight, m_pluginBounds.fBottom); #endif // change the visibility m_visible = visible; // send the event ANPEvent event; SkANP::InitEvent(&event, kLifecycle_ANPEventType); event.data.lifecycle.action = visible ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction; sendEvent(event); } }
void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { // store the reference locally for easy lookup m_pluginWindow = window; // make a copy of the previous bounds SkIRect oldPluginBounds = m_pluginBounds; // keep a local copy of the plugin bounds because the m_pluginWindow pointer // gets updated values prior to this method being called m_pluginBounds.set(m_pluginWindow->x, m_pluginWindow->y, m_pluginWindow->x + m_pluginWindow->width, m_pluginWindow->y + m_pluginWindow->height); PLUGIN_LOG("%p PluginBounds (%d,%d,%d,%d)", m_pluginView->instance(), m_pluginBounds.fLeft, m_pluginBounds.fTop, m_pluginBounds.fRight, m_pluginBounds.fBottom); layoutSurface(m_pluginBounds != oldPluginBounds); if (m_drawingModel != kSurface_ANPDrawingModel) { m_flipPixelRef->safeUnref(); m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), window->width, window->height); } }
PluginWidgetAndroid::~PluginWidgetAndroid() { PLUGIN_LOG("%p Deleting Plugin", m_pluginView->instance()); m_acceptEvents = false; if (m_core && android::WebViewCore::isInstance(m_core)) { m_core->removePlugin(this); if (m_isFullScreen) { exitFullScreen(true); } //SAMSUNG CHANGES //Rakesh: Added a check to see whether surface to be //destroyed is valid or not if (m_embeddedView && m_embeddedViewAttached) { m_core->destroySurface(m_embeddedView); m_embeddedViewAttached = false; } //SAMSUNG CHANGES } // cleanup any remaining JNI References JNIEnv* env = JSC::Bindings::getJNIEnv(); if (m_embeddedView) { env->DeleteGlobalRef(m_embeddedView); } m_flipPixelRef->safeUnref(); }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable( nsIRequest* request, nsIInputStream* aIStream, uint64_t sourceOffset, uint32_t aLength) { if (mRequests.IndexOfObject(request) == -1) { MOZ_ASSERT(false, "Received OnDataAvailable for untracked request."); return NS_ERROR_UNEXPECTED; } if (mRequestFailed) return NS_ERROR_FAILURE; nsresult rv = NS_OK; if (!mPStreamListener) return NS_ERROR_FAILURE; const char* url = nullptr; GetURL(&url); PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, " "offset=%" PRIu64 ", length=%u, url=%s\n", this, request, sourceOffset, aLength, url ? url : "no url set")); nsCOMPtr<nsIInputStream> stream = aIStream; rv = mPStreamListener->OnDataAvailable(this, stream, aLength); // if a plugin returns an error, the peer must kill the stream // else the stream and PluginStreamListener leak if (NS_FAILED(rv)) { request->Cancel(rv); } return rv; }
void PluginWidgetAndroid::setFullScreenOrientation(ANPScreenOrientation orientation) { int internalOrienationId; /* We need to validate that the input is legitimate and then convert the * value from the plugin enum to the enum used by the android view system. * The view system values correspond to those values for the * screenOrientation attribute in R.java (see also ActivityInfo.java). */ switch (orientation) { case kFixedLandscape_ANPScreenOrientation: internalOrienationId = 0; break; case kFixedPortrait_ANPScreenOrientation: internalOrienationId = 1; break; case kLandscape_ANPScreenOrientation: internalOrienationId = 6; break; case kPortrait_ANPScreenOrientation: internalOrienationId = 7; break; default: internalOrienationId = -1; } PLUGIN_LOG("%s orientation (%d)", __FUNCTION__, internalOrienationId); m_fullScreenOrientation = internalOrienationId; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest* request, nsresult aStatus) { nsresult rv = NS_OK; nsCOMPtr<nsIMultiPartChannel> mp = do_QueryInterface(request); if (!mp) { bool found = mRequests.RemoveObject(request); if (!found) { NS_ERROR("Received OnStopRequest for untracked request."); } } PLUGIN_LOG( PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%" PRIu32 " request=%p\n", this, static_cast<uint32_t>(aStatus), request)); // if we still have pending stuff to do, lets not close the plugin socket. if (--mPendingRequests > 0) return NS_OK; if (!mPStreamListener) return NS_ERROR_FAILURE; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); if (!channel) return NS_ERROR_FAILURE; // Set the content type to ensure we don't pass null to the plugin nsAutoCString aContentType; rv = channel->GetContentType(aContentType); if (NS_FAILED(rv) && !mRequestFailed) return rv; if (!aContentType.IsEmpty()) mContentType = aContentType; // set error status if stream failed so we notify the plugin if (mRequestFailed) aStatus = NS_ERROR_FAILURE; if (NS_FAILED(aStatus)) { // on error status cleanup the stream // and return w/o OnFileAvailable() mPStreamListener->OnStopBinding(this, aStatus); return NS_OK; } if (mStartBinding) { // On start binding has been called mPStreamListener->OnStopBinding(this, aStatus); } else { // OnStartBinding hasn't been called, so complete the action. mPStreamListener->OnStartBinding(this); mPStreamListener->OnStopBinding(this, aStatus); } if (NS_SUCCEEDED(aStatus)) { mStreamComplete = true; } return NS_OK; }
void PluginWidgetAndroid::sendSizeAndVisibilityEvents(const bool updateDimensions) { if (m_drawingModel == kOpenGL_ANPDrawingModel && !m_layer->acquireNativeWindowForContent()) { m_drawEventDelayed = true; return; } // TODO update the bitmap size based on the zoom? (for kBitmap_ANPDrawingModel) const float zoomLevel = m_core->scale(); // notify the plugin of the new size if (m_drawingModel == kOpenGL_ANPDrawingModel && updateDimensions && m_pluginWindow) { PLUGIN_LOG("%s (%d,%d)[%f]", __FUNCTION__, m_pluginWindow->width, m_pluginWindow->height, zoomLevel); ANPEvent event; SkANP::InitEvent(&event, kDraw_ANPEventType); event.data.draw.model = kOpenGL_ANPDrawingModel; event.data.draw.data.surface.width = m_pluginWindow->width * zoomLevel; event.data.draw.data.surface.height = m_pluginWindow->height * zoomLevel; sendEvent(event); } bool visible = SkIRect::Intersects(m_visibleDocRect, m_pluginBounds); if(m_visible != visible) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%p changeVisiblity[%d] pluginBounds(%d,%d,%d,%d)", m_pluginView->instance(), visible, m_pluginBounds.fLeft, m_pluginBounds.fTop, m_pluginBounds.fRight, m_pluginBounds.fBottom); #endif // change the visibility m_visible = visible; // send the event ANPEvent event; SkANP::InitEvent(&event, kLifecycle_ANPEventType); event.data.lifecycle.action = visible ? kOnScreen_ANPLifecycleAction : kOffScreen_ANPLifecycleAction; sendEvent(event); } }
void PluginWidgetAndroid::computeVisiblePluginRect() { // ensure the visibleDocRect has been set (i.e. not equal to zero) if (m_visibleDocRect.isEmpty() || !m_pluginWindow || m_requestedVisibleRectCount < 1) return; // create a rect that will contain as many of the rects that will fit on screen SkIRect visibleRect; visibleRect.setEmpty(); for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) { ANPRectI* rect = &m_requestedVisibleRects[counter]; // create skia rect for easier manipulation and convert it to page coordinates SkIRect pluginRect; pluginRect.set(rect->left, rect->top, rect->right, rect->bottom); pluginRect.offset(m_pluginWindow->x, m_pluginWindow->y); // ensure the rect falls within the plugin's bounds if (!m_pluginBounds.contains(pluginRect)) { #if DEBUG_VISIBLE_RECTS PLUGIN_LOG("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__, m_pluginBounds.fLeft, m_pluginBounds.fTop, m_pluginBounds.fRight, m_pluginBounds.fBottom, pluginRect.fLeft, pluginRect.fTop, pluginRect.fRight, pluginRect.fBottom); // assume that the desired outcome is to clamp to the container if (pluginRect.intersect(m_pluginBounds)) { visibleRect = pluginRect; } #endif continue; } // combine this new rect with the higher priority rects pluginRect.join(visibleRect); // check to see if the new rect could be made to fit within the screen // bounds. If this is the highest priority rect then attempt to center // even if it doesn't fit on the screen. if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() || m_visibleDocRect.height() < pluginRect.height())) break; // set the new visible rect visibleRect = pluginRect; } m_requestedVisibleRect = visibleRect; scrollToVisiblePluginRect(); }
int auth_user_pass_verify_handler_func(void *handler_context) { int r = 0; int http_code; deferred_handler_context_t *context = (deferred_handler_context_t*)handler_context; const char *auth_control_file = get_openvpn_env( "auth_control_file", (const char**)(context->envp)); const char *username = get_openvpn_env("username", (const char**)(context->envp)); /* I do not see any reasons why web server should know auth_control_file * to auth user. */ static const char *exclude_list[] = {"auth_control_file", NULL}; char *json_envp = openvpn_envp_to_json((const char **)context->envp, exclude_list); if (!username) username = ""; PLUGIN_DEBUG("START - auth_user_pass_verify_handler_func."); PLUGIN_DEBUG("Data to post: %s. To URL: %s. auth_control_file: %s.", json_envp, context->handler_url, auth_control_file); http_code = send_post(context->handler_url, json_envp); PLUGIN_DEBUG("HTTP Response code: %d.", http_code); if (http_code == 200) { PLUGIN_LOG("Auth for user %s SUCCESS.", username); write_auth_control_file(auth_control_file, 1); } else { PLUGIN_LOG("Auth for user %s FAILED.", username); write_auth_control_file(auth_control_file, 0); } free(json_envp); PLUGIN_DEBUG("END - auth_user_pass_verify_handler_func."); return r; }
static bool getEntryPoint(PlatformModule module, const char *name, void **entry_point) { dlerror(); *entry_point = dlsym(module, name); const char *error = dlerror(); if(error == NULL && *entry_point != NULL) { return true; } else { PLUGIN_LOG("Couldn't get entry point \"%s\": %s\n", name, error); return false; } }
void PluginWidgetAndroid::layoutSurface(bool pluginBoundsChanged) { if (m_drawingModel != kSurface_ANPDrawingModel) return; if (!m_pluginWindow) return; bool displayPlugin = m_pluginView->isVisible() && !m_isSurfaceClippedOut; PLUGIN_LOG("%p DisplayPlugin[%d] visible=[%d] clipped=[%d]", m_pluginView->instance(), displayPlugin, m_pluginView->isVisible(), m_isSurfaceClippedOut); // if the surface does not exist then create a new surface if (!m_embeddedView && displayPlugin) { WebCore::PluginPackage* pkg = m_pluginView->plugin(); NPP instance = m_pluginView->instance(); jobject pluginSurface; pkg->pluginFuncs()->getvalue(instance, kJavaSurface_ANPGetValue, static_cast<void*>(&pluginSurface)); jobject tempObj = m_core->addSurface(pluginSurface, m_pluginWindow->x, m_pluginWindow->y, m_pluginWindow->width, m_pluginWindow->height); if (tempObj) { JNIEnv* env = JSC::Bindings::getJNIEnv(); m_embeddedView = env->NewGlobalRef(tempObj); m_embeddedViewAttached = true; } // if the view is unattached but visible then attach it } else if (m_embeddedView && !m_embeddedViewAttached && displayPlugin && !m_isFullScreen) { m_core->updateSurface(m_embeddedView, m_pluginWindow->x, m_pluginWindow->y, m_pluginWindow->width, m_pluginWindow->height); m_embeddedViewAttached = true; // if the view is attached but invisible then remove it } else if (m_embeddedView && m_embeddedViewAttached && !displayPlugin) { m_core->destroySurface(m_embeddedView); m_embeddedViewAttached = false; // if the plugin's bounds have changed and it's visible then update it } else if (pluginBoundsChanged && displayPlugin && !m_isFullScreen) { m_core->updateSurface(m_embeddedView, m_pluginWindow->x, m_pluginWindow->y, m_pluginWindow->width, m_pluginWindow->height); } }
// Called by NewFullPagePluginStream() nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIURI* aURL, nsNPAPIPluginInstance *aInstance) { PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginStreamListenerPeer::InitializeFullPage instance=%p\n",aInstance)); NS_ASSERTION(mPluginInstance == nsnull, "nsPluginStreamListenerPeer::InitializeFullPage mPluginInstance != nsnull"); mPluginInstance = aInstance; mURL = aURL; mDataForwardToRequest = new nsHashtable(16, false); if (!mDataForwardToRequest) return NS_ERROR_FAILURE; mPendingRequests = 1; return NS_OK; }
PluginWidgetAndroid::~PluginWidgetAndroid() { PLUGIN_LOG("%p Deleting Plugin", m_pluginView->instance()); m_acceptEvents = false; if (m_core) { m_core->removePlugin(this); if (m_isFullScreen) { exitFullScreen(true); } if (m_embeddedView) { m_core->destroySurface(m_embeddedView); } } // cleanup any remaining JNI References JNIEnv* env = JSC::Bindings::getJNIEnv(); if (m_embeddedView) { env->DeleteGlobalRef(m_embeddedView); } m_flipPixelRef->safeUnref(); }
void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { // store the reference locally for easy lookup m_pluginWindow = window; // make a copy of the previous bounds SkIRect oldPluginBounds = m_pluginBounds; // keep a local copy of the plugin bounds because the m_pluginWindow pointer // gets updated values prior to this method being called m_pluginBounds.set(m_pluginWindow->x, m_pluginWindow->y, m_pluginWindow->x + m_pluginWindow->width, m_pluginWindow->y + m_pluginWindow->height); PLUGIN_LOG("%p PluginBounds (%d,%d,%d,%d)", m_pluginView->instance(), m_pluginBounds.fLeft, m_pluginBounds.fTop, m_pluginBounds.fRight, m_pluginBounds.fBottom); const bool boundsChanged = m_pluginBounds != oldPluginBounds; //TODO hack to ensure that we grab the most recent screen dimensions and scale ANPRectI screenCoords; m_core->getVisibleScreen(screenCoords); float scale = m_core->scale(); bool scaleChanged = m_cachedZoomLevel != scale; setVisibleScreen(screenCoords, scale); // if the scale changed then setVisibleScreen will call this function and // this call will potentially fire a duplicate draw event if (!scaleChanged) { sendSizeAndVisibilityEvents(boundsChanged); } layoutSurface(boundsChanged); if (m_drawingModel != kSurface_ANPDrawingModel) { SkSafeUnref(m_flipPixelRef); m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), window->width, window->height); } }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest *request, nsISupports* aContext, nsresult aStatus) { nsresult rv = NS_OK; nsCOMPtr<nsIMultiPartChannel> mp = do_QueryInterface(request); if (!mp) { bool found = mRequests.RemoveObject(request); if (!found) { NS_ERROR("Received OnStopRequest for untracked request."); } } PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%d request=%p\n", this, aStatus, request)); // for ByteRangeRequest we're just updating the mDataForwardToRequest hash and return. nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request); if (brr) { int64_t absoluteOffset64 = 0; brr->GetStartRange(&absoluteOffset64); // XXX support 64-bit offsets int32_t absoluteOffset = (int32_t)int64_t(absoluteOffset64); // remove the request from our data forwarding count hash. mDataForwardToRequest->Remove(absoluteOffset); PLUGIN_LOG(PLUGIN_LOG_NOISY, (" ::OnStopRequest for ByteRangeRequest Started=%d\n", absoluteOffset)); } else { // if this is not byte range request and // if we are writting the stream to disk ourselves, // close & tear it down here mFileCacheOutputStream = nullptr; } // if we still have pending stuff to do, lets not close the plugin socket. if (--mPendingRequests > 0) return NS_OK; // we keep our connections around... nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext); if (container) { uint32_t magicNumber = 0; // set it to something that is not the magic number. container->GetData(&magicNumber); if (magicNumber == MAGIC_REQUEST_CONTEXT) { // this is one of our range requests return NS_OK; } } if (!mPStreamListener) return NS_ERROR_FAILURE; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); if (!channel) return NS_ERROR_FAILURE; // Set the content type to ensure we don't pass null to the plugin nsAutoCString aContentType; rv = channel->GetContentType(aContentType); if (NS_FAILED(rv) && !mRequestFailed) return rv; if (!aContentType.IsEmpty()) mContentType = aContentType; // set error status if stream failed so we notify the plugin if (mRequestFailed) aStatus = NS_ERROR_FAILURE; if (NS_FAILED(aStatus)) { // on error status cleanup the stream // and return w/o OnFileAvailable() mPStreamListener->OnStopBinding(this, aStatus); return NS_OK; } // call OnFileAvailable if plugin requests stream type StreamType_AsFile or StreamType_AsFileOnly if (mStreamType >= NP_ASFILE) { nsCOMPtr<nsIFile> localFile; if (mLocalCachedFileHolder) localFile = mLocalCachedFileHolder->file(); else { // see if it is a file channel. nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request); if (fileChannel) { fileChannel->GetFile(getter_AddRefs(localFile)); } } if (localFile) { OnFileAvailable(localFile); } } if (mStartBinding) { // On start binding has been called mPStreamListener->OnStopBinding(this, aStatus); } else { // OnStartBinding hasn't been called, so complete the action. mPStreamListener->OnStartBinding(this); mPStreamListener->OnStopBinding(this, aStatus); } if (NS_SUCCEEDED(aStatus)) { mStreamComplete = true; } return NS_OK; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, nsISupports* aContext, nsIInputStream *aIStream, uint64_t sourceOffset, uint32_t aLength) { if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) { MOZ_ASSERT(false, "Received OnDataAvailable for untracked request."); return NS_ERROR_UNEXPECTED; } if (mRequestFailed) return NS_ERROR_FAILURE; if (mAbort) { uint32_t magicNumber = 0; // set it to something that is not the magic number. nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext); if (container) container->GetData(&magicNumber); if (magicNumber != MAGIC_REQUEST_CONTEXT) { // this is not one of our range requests mAbort = false; return NS_BINDING_ABORTED; } } nsresult rv = NS_OK; if (!mPStreamListener) return NS_ERROR_FAILURE; const char * url = nullptr; GetURL(&url); PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, offset=%llu, length=%u, url=%s\n", this, request, sourceOffset, aLength, url ? url : "no url set")); // if the plugin has requested an AsFileOnly stream, then don't // call OnDataAvailable if (mStreamType != NP_ASFILEONLY) { // get the absolute offset of the request, if one exists. nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request); if (brr) { if (!mDataForwardToRequest) return NS_ERROR_FAILURE; int64_t absoluteOffset64 = 0; brr->GetStartRange(&absoluteOffset64); // XXX handle 64-bit for real int32_t absoluteOffset = (int32_t)int64_t(absoluteOffset64); // we need to track how much data we have forwarded to the // plugin. // FIXME: http://bugzilla.mozilla.org/show_bug.cgi?id=240130 // // Why couldn't this be tracked on the plugin info, and not in a // *hash table*? int32_t amtForwardToPlugin = mDataForwardToRequest->Get(absoluteOffset); mDataForwardToRequest->Put(absoluteOffset, (amtForwardToPlugin + aLength)); SetStreamOffset(absoluteOffset + amtForwardToPlugin); } nsCOMPtr<nsIInputStream> stream = aIStream; // if we are caching the file ourselves to disk, we want to 'tee' off // the data as the plugin read from the stream. We do this by the magic // of an input stream tee. if (mFileCacheOutputStream) { rv = NS_NewInputStreamTee(getter_AddRefs(stream), aIStream, mFileCacheOutputStream); if (NS_FAILED(rv)) return rv; } rv = mPStreamListener->OnDataAvailable(this, stream, aLength); // if a plugin returns an error, the peer must kill the stream // else the stream and PluginStreamListener leak if (NS_FAILED(rv)) request->Cancel(rv); } else { // if we don't read from the stream, OnStopRequest will never be called char* buffer = new char[aLength]; uint32_t amountRead, amountWrote = 0; rv = aIStream->Read(buffer, aLength, &amountRead); // if we are caching this to disk ourselves, lets write the bytes out. if (mFileCacheOutputStream) { while (amountWrote < amountRead && NS_SUCCEEDED(rv)) { rv = mFileCacheOutputStream->Write(buffer, amountRead, &amountWrote); } } delete [] buffer; } return rv; }
bool PluginPackage::fetchInfo() { PLUGIN_LOG("Fetch Info Loading \"%s\"\n", m_path.utf8().data()); // Open the library void *handle = dlopen(m_path.utf8().data(), RTLD_NOW); if(!handle) { PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n", m_path.utf8().data(), dlerror()); return false; } PLUGIN_LOG("Fetch Info Loaded %p\n", handle); // This object will call dlclose() and set m_module to NULL // when going out of scope. DynamicLibraryCloser dlCloser(&handle); // Get the three entry points we need for Linux Netscape Plug-ins NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription; NPP_GetValueProcPtr NP_GetValue; if(!getEntryPoint(handle, "NP_GetMIMEDescription", (void **) &NP_GetMIMEDescription) || !getEntryPoint(handle, "NP_GetValue", (void **) &NP_GetValue)) { // If any of those failed to resolve, fail the entire load return false; } // Get the plugin name and description using NP_GetValue const char *name; const char *description; if(NP_GetValue(NULL, NPPVpluginNameString, &name) != NPERR_NO_ERROR || NP_GetValue(NULL, NPPVpluginDescriptionString, &description) != NPERR_NO_ERROR) { PLUGIN_LOG("Couldn't get name/description using NP_GetValue\n"); return false; } PLUGIN_LOG("Plugin name: \"%s\"\n", name); PLUGIN_LOG("Plugin description: \"%s\"\n", description); m_name = name; m_description = description; // fileName is just the trailing part of the path int last_slash = m_path.reverseFind('/'); if(last_slash < 0) m_fileName = m_path; else m_fileName = m_path.substring(last_slash + 1); // Grab the MIME description. This is in the format, e.g: // application/x-somescriptformat:ssf:Some Script Format String mimeDescription(NP_GetMIMEDescription()); PLUGIN_LOG("MIME description: \"%s\"\n", mimeDescription.utf8().data()); // Clear out the current mappings. m_mimeToDescriptions.clear(); m_mimeToExtensions.clear(); // Split the description into its component entries, separated by // semicolons. Vector<String> mimeEntries; mimeDescription.split(';', true, mimeEntries); // Iterate through the entries, adding them to the MIME mappings. for(Vector<String>::const_iterator it = mimeEntries.begin(); it != mimeEntries.end(); ++it) { // Each part is split into 3 fields separated by colons // Field 1 is the MIME type (e.g "application/x-shockwave-flash"). // Field 2 is a comma separated list of file extensions. // Field 3 is a human readable short description. const String &mimeEntry = *it; Vector<String> fields; mimeEntry.split(':', true, fields); if(fields.size() != 3) { PLUGIN_LOG("Bad MIME entry \"%s\"\n", mimeEntry.utf8().data()); return false; } const String& mimeType = fields[0]; Vector<String> extensions; fields[1].split(',', true, extensions); const String& description = fields[2]; determineQuirks(mimeType); PLUGIN_LOG("mime_type: \"%s\"\n", mimeType.utf8().data()); PLUGIN_LOG("extensions: \"%s\"\n", fields[1].utf8().data()); PLUGIN_LOG("description: \"%s\"\n", description.utf8().data()); // Map the mime type to the vector of extensions and the description if(!extensions.isEmpty()) m_mimeToExtensions.set(mimeType, extensions); if(!description.isEmpty()) m_mimeToDescriptions.set(mimeType, description); } PLUGIN_LOG("Fetch Info Loaded plugin details ok \"%s\"\n", m_path.utf8().data()); // If this plugin needs to be kept in memory, unload the module now // and load it permanently. if (m_quirks.contains(PluginQuirkDontUnloadPlugin)) { dlCloser.ok(); dlclose(handle); load(); } // dlCloser will unload the plugin if required. return true; }
bool PluginPackage::load() { PLUGIN_LOG("tid:%d isActive:%d isLoaded:%d loadCount:%d\n", gettid(), m_freeLibraryTimer.isActive(), m_isLoaded, m_loadCount); if (m_freeLibraryTimer.isActive()) { ASSERT(m_module); m_freeLibraryTimer.stop(); } else if (m_isLoaded) { if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances)) return false; m_loadCount++; PLUGIN_LOG("Already loaded, count now %d\n", m_loadCount); return true; } ASSERT(m_loadCount == 0); ASSERT(m_module == NULL); PLUGIN_LOG("Loading \"%s\"\n", m_path.utf8().data()); // Open the library void *handle = dlopen(m_path.utf8().data(), RTLD_NOW); if(!handle) { PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n", m_path.utf8().data(), dlerror()); return false; } m_module = handle; PLUGIN_LOG("Fetch Info Loaded %p\n", m_module); // This object will call dlclose() and set m_module to NULL // when going out of scope. DynamicLibraryCloser dlCloser(&m_module); NP_InitializeFuncPtr NP_Initialize; if(!getEntryPoint(m_module, "NP_Initialize", (void **) &NP_Initialize) || !getEntryPoint(handle, "NP_Shutdown", (void **) &m_NPP_Shutdown)) { PLUGIN_LOG("Couldn't find Initialize function\n"); return false; } // Provide the plugin with our browser function table and grab its // plugin table. Provide the Java environment and the Plugin which // can be used to override the defaults if the plugin wants. initializeBrowserFuncs(); // call this afterwards, which may re-initialize some methods, but ensures // that any additional (or changed) procs are set. There is no real attempt // to have this step be minimal (i.e. only what we add/override), since the // core version (initializeBrowserFuncs) can change in the future. initializeExtraBrowserFuncs(&m_browserFuncs); memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); m_pluginFuncs.size = sizeof(m_pluginFuncs); if(NP_Initialize(&m_browserFuncs, &m_pluginFuncs, JSC::Bindings::getJNIEnv()) != NPERR_NO_ERROR) { PLUGIN_LOG("Couldn't initialize plugin\n"); return false; } // Don't close the library - loaded OK. dlCloser.ok(); // Retain the handle so we can close it in the future. m_module = handle; m_isLoaded = true; ++m_loadCount; PLUGIN_LOG("Initial load ok, count now %d\n", m_loadCount); return true; }
void anp_logPluginEvent(void* npp, const ANPEvent* evt, int16 returnVal, int elapsedTime) { switch(evt->eventType) { case kNull_ANPEventType: PLUGIN_LOG("%p EVENT::NULL", npp); break; case kKey_ANPEventType: if(evt->data.key.action < ARRAY_COUNT(inputActions)) { anp_logPlugin("%p EVENT::KEY[%d] time=%d action=%s code=%d vcode=%d unichar=%d repeat=%d mods=%x", npp, returnVal, elapsedTime, inputActions[evt->data.key.action], evt->data.key.nativeCode, evt->data.key.virtualCode, evt->data.key.unichar, evt->data.key.repeatCount, evt->data.key.modifiers); } else { PLUGIN_LOG("%p EVENT::KEY[%d] unknown action", npp, returnVal); } break; case kMouse_ANPEventType: if(evt->data.mouse.action < ARRAY_COUNT(inputActions)) { anp_logPlugin("%p EVENT::MOUSE[%d] time=%d action=%s [%d %d]", npp, returnVal, elapsedTime, inputActions[evt->data.mouse.action], evt->data.touch.x, evt->data.touch.y); } else { anp_logPlugin("%p EVENT::MOUSE[%d] unknown action", npp, returnVal); } break; case kTouch_ANPEventType: if(evt->data.touch.action < ARRAY_COUNT(inputActions)) { anp_logPlugin("%p EVENT::TOUCH[%d] time=%d action=%s [%d %d]", npp, returnVal, elapsedTime, inputActions[evt->data.touch.action], evt->data.touch.x, evt->data.touch.y); } else { anp_logPlugin("%p EVENT::TOUCH[%d] unknown action", npp, returnVal); } break; case kDraw_ANPEventType: if (evt->data.draw.model == kBitmap_ANPDrawingModel) { anp_logPlugin("%p EVENT::DRAW bitmap time=%d format=%d clip=[%d,%d,%d,%d]", npp, elapsedTime, evt->data.draw.data.bitmap.format, evt->data.draw.clip.left, evt->data.draw.clip.top, evt->data.draw.clip.right, evt->data.draw.clip.bottom); } else { anp_logPlugin("%p EVENT::DRAW unknown drawing model", npp); } break; case kLifecycle_ANPEventType: if(evt->data.lifecycle.action < ARRAY_COUNT(lifecycleActions)) { anp_logPlugin("%p EVENT::LIFECYCLE time=%d action=%s", npp, elapsedTime, lifecycleActions[evt->data.lifecycle.action]); } else { anp_logPlugin("%p EVENT::LIFECYCLE unknown action", npp); } break; case kCustom_ANPEventType: anp_logPlugin("%p EVENT::CUSTOM time=%d", npp, elapsedTime); break; default: anp_logPlugin("%p EVENT::UNKNOWN", npp); break; } }
void PluginWidgetAndroid::init(android::WebViewCore* core) { m_core = core; m_core->addPlugin(this); m_acceptEvents = true; PLUGIN_LOG("%p Initialized Plugin", m_pluginView->instance()); }