PassOwnPtr<AudioBus> AudioFileReader::createBus(float sampleRate, bool mixToMono) { m_sampleRate = sampleRate; m_frontLeftBuffers = gst_buffer_list_new(); m_frontRightBuffers = gst_buffer_list_new(); #ifndef GST_API_VERSION_1 m_frontLeftBuffersIterator = gst_buffer_list_iterate(m_frontLeftBuffers); gst_buffer_list_iterator_add_group(m_frontLeftBuffersIterator); m_frontRightBuffersIterator = gst_buffer_list_iterate(m_frontRightBuffers); gst_buffer_list_iterator_add_group(m_frontRightBuffersIterator); #endif GRefPtr<GMainContext> context = adoptGRef(g_main_context_new()); g_main_context_push_thread_default(context.get()); m_loop = adoptGRef(g_main_loop_new(context.get(), FALSE)); // Start the pipeline processing just after the loop is started. GRefPtr<GSource> timeoutSource = adoptGRef(g_timeout_source_new(0)); g_source_attach(timeoutSource.get(), context.get()); g_source_set_callback(timeoutSource.get(), reinterpret_cast<GSourceFunc>(enteredMainLoopCallback), this, 0); g_main_loop_run(m_loop.get()); g_main_context_pop_thread_default(context.get()); if (m_errorOccurred) return nullptr; unsigned channels = mixToMono ? 1 : 2; OwnPtr<AudioBus> audioBus = adoptPtr(new AudioBus(channels, m_channelSize, true)); audioBus->setSampleRate(m_sampleRate); copyGstreamerBuffersToAudioChannel(m_frontLeftBuffers, audioBus->channel(0)); if (!mixToMono) copyGstreamerBuffersToAudioChannel(m_frontRightBuffers, audioBus->channel(1)); return audioBus.release(); }
void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) { GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkit_file_chooser_request_create(prpFileChooser)); webkitWebViewRunFileChooserRequest(m_webView, request.get()); }
static void webkitCookieManagerGetAcceptPolicyCallback(WKHTTPCookieAcceptPolicy policy, WKErrorRef, void* context) { GRefPtr<GTask> task = adoptGRef(G_TASK(context)); g_task_return_int(task.get(), policy); }
// This function creates and initializes some internal variables, and returns a // pointer to the element that should receive the data flow first GstElement* MediaPlayerPrivateGStreamerBase::createVideoSink(GstElement* pipeline) { if (!initializeGStreamer()) return 0; #if USE(NATIVE_FULLSCREEN_VIDEO) m_gstGWorld = GStreamerGWorld::createGWorld(pipeline); m_webkitVideoSink = webkitVideoSinkNew(m_gstGWorld.get()); #else UNUSED_PARAM(pipeline); m_webkitVideoSink = webkitVideoSinkNew(); #endif m_repaintHandler = g_signal_connect(m_webkitVideoSink.get(), "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this); #if USE(NATIVE_FULLSCREEN_VIDEO) // Build a new video sink consisting of a bin containing a tee // (meant to distribute data to multiple video sinks) and our // internal video sink. For fullscreen we create an autovideosink // and initially block the data flow towards it and configure it m_videoSinkBin = gst_bin_new("video-sink"); GstElement* videoTee = gst_element_factory_make("tee", "videoTee"); GstElement* queue = gst_element_factory_make("queue", 0); #ifdef GST_API_VERSION_1 GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(videoTee, "sink")); GST_OBJECT_FLAG_SET(GST_OBJECT(sinkPad.get()), GST_PAD_FLAG_PROXY_ALLOCATION); #endif gst_bin_add_many(GST_BIN(m_videoSinkBin.get()), videoTee, queue, NULL); // Link a new src pad from tee to queue1. gst_element_link_pads_full(videoTee, 0, queue, "sink", GST_PAD_LINK_CHECK_NOTHING); #endif GstElement* actualVideoSink = 0; m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink"); if (m_fpsSink) { // The verbose property has been added in -bad 0.10.22. Making // this whole code depend on it because we don't want // fpsdiplaysink to spit data on stdout. GstElementFactory* factory = GST_ELEMENT_FACTORY(GST_ELEMENT_GET_CLASS(m_fpsSink)->elementfactory); if (gst_plugin_feature_check_version(GST_PLUGIN_FEATURE(factory), 0, 10, 22)) { g_object_set(m_fpsSink, "silent", TRUE , NULL); // Turn off text overlay unless logging is enabled. #if LOG_DISABLED g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); #else WTFLogChannel* channel = getChannelFromName("Media"); if (channel->state != WTFLogChannelOn) g_object_set(m_fpsSink, "text-overlay", FALSE , NULL); #endif // LOG_DISABLED if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) { g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink.get(), NULL); #if USE(NATIVE_FULLSCREEN_VIDEO) gst_bin_add(GST_BIN(m_videoSinkBin.get()), m_fpsSink); #endif actualVideoSink = m_fpsSink; } else m_fpsSink = 0; } else m_fpsSink = 0; } if (!m_fpsSink) { #if USE(NATIVE_FULLSCREEN_VIDEO) gst_bin_add(GST_BIN(m_videoSinkBin.get()), m_webkitVideoSink.get()); #endif actualVideoSink = m_webkitVideoSink.get(); } ASSERT(actualVideoSink); #if USE(NATIVE_FULLSCREEN_VIDEO) // Faster elements linking. gst_element_link_pads_full(queue, "src", actualVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING); // Add a ghostpad to the bin so it can proxy to tee. GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(videoTee, "sink")); gst_element_add_pad(m_videoSinkBin.get(), gst_ghost_pad_new("sink", pad.get())); // Set the bin as video sink of playbin. return m_videoSinkBin.get(); #else return actualVideoSink; #endif }
std::unique_ptr<SoupNetworkSession> SoupNetworkSession::createTestingSession() { GRefPtr<SoupCookieJar> cookieJar = adoptGRef(createPrivateBrowsingCookieJar()); return std::unique_ptr<SoupNetworkSession>(new SoupNetworkSession(cookieJar.get())); }
static GRefPtr<GdkCursor> createCustomCursor(Image* image, const IntPoint& hotSpot) { IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); GRefPtr<GdkPixbuf> pixbuf = adoptGRef(image->getGdkPixbuf()); return adoptGRef(gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf.get(), effectiveHotSpot.x(), effectiveHotSpot.y())); }
static void didInitiateLoadForResource(WKPageRef, WKFrameRef wkFrame, uint64_t resourceIdentifier, WKURLRequestRef wkRequest, bool pageIsProvisionallyLoading, const void* clientInfo) { GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(toImpl(wkRequest)->resourceRequest())); webkitWebViewResourceLoadStarted(WEBKIT_WEB_VIEW(clientInfo), toImpl(wkFrame), resourceIdentifier, request.get()); }
virtual bool decidePolicyForGeolocationPermissionRequest(WebPageProxy*, WebFrameProxy*, WebSecurityOrigin*, GeolocationPermissionRequestProxy* permissionRequest) override { GRefPtr<WebKitGeolocationPermissionRequest> geolocationPermissionRequest = adoptGRef(webkitGeolocationPermissionRequestCreate(permissionRequest)); webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(geolocationPermissionRequest.get())); return true; }
static void decidePolicyForGeolocationPermissionRequest(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKGeolocationPermissionRequestRef request, const void* clientInfo) { GRefPtr<WebKitGeolocationPermissionRequest> geolocationPermissionRequest = adoptGRef(webkitGeolocationPermissionRequestCreate(toImpl(request))); webkitWebViewMakePermissionRequest(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_PERMISSION_REQUEST(geolocationPermissionRequest.get())); }
static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void *clientInfo) { GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkitFileChooserRequestCreate(toImpl(parameters), toImpl(listener))); webkitWebViewRunFileChooserRequest(WEBKIT_WEB_VIEW(clientInfo), request.get()); }
void GStreamerGWorld::removePlatformVideoSink() { if (!m_dynamicPadName) return; // Get video sink bin and the elements to remove. GstElement* sinkPtr = 0; g_object_get(m_pipeline, "video-sink", &sinkPtr, NULL); GRefPtr<GstElement> videoSink = adoptGRef(sinkPtr); GRefPtr<GstElement> tee = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee")); GRefPtr<GstElement> platformVideoSink = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "platformVideoSink")); GRefPtr<GstElement> queue = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "queue")); GRefPtr<GstElement> colorspace = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "colorspace")); GRefPtr<GstElement> videoScale = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoScale")); GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_static_pad(tee.get(), m_dynamicPadName.get())); GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(queue.get(), "sink")); gst_pad_unlink(srcPad.get(), sinkPad.get()); gst_element_release_request_pad(tee.get(), srcPad.get()); gst_element_unlink_many(queue.get(), colorspace.get(), videoScale.get(), platformVideoSink.get(), NULL); gst_bin_remove_many(GST_BIN(videoSink.get()), queue.get(), colorspace.get(), videoScale.get(), platformVideoSink.get(), NULL); gst_element_set_state(platformVideoSink.get(), GST_STATE_NULL); gst_element_set_state(videoScale.get(), GST_STATE_NULL); gst_element_set_state(colorspace.get(), GST_STATE_NULL); gst_element_set_state(queue.get(), GST_STATE_NULL); m_dynamicPadName.clear(); }
bool GStreamerGWorld::enterFullscreen() { if (m_dynamicPadName) return false; if (!m_videoWindow) m_videoWindow = PlatformVideoWindow::createWindow(); GstElement* platformVideoSink = gst_element_factory_make("autovideosink", "platformVideoSink"); GstElement* colorspace = gst_element_factory_make(gVideoConvertName, "colorspace"); GstElement* queue = gst_element_factory_make("queue", "queue"); GstElement* videoScale = gst_element_factory_make("videoscale", "videoScale"); // Get video sink bin and the tee inside. GRefPtr<GstElement> videoSink; GstElement* sinkPtr = 0; g_object_get(m_pipeline, "video-sink", &sinkPtr, NULL); videoSink = adoptGRef(sinkPtr); GRefPtr<GstElement> tee = adoptGRef(gst_bin_get_by_name(GST_BIN(videoSink.get()), "videoTee")); gst_bin_add_many(GST_BIN(videoSink.get()), platformVideoSink, videoScale, colorspace, queue, NULL); // Faster elements linking. gst_element_link_pads_full(queue, "src", colorspace, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(colorspace, "src", videoScale, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(videoScale, "src", platformVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING); // Link a new src pad from tee to queue. #ifndef GST_API_VERSION_1 GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_request_pad(tee.get(), "src%d")); #else GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_request_pad(tee.get(), "src_%u")); #endif GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(queue, "sink")); gst_pad_link(srcPad.get(), sinkPad.get()); m_dynamicPadName.set(gst_pad_get_name(srcPad.get())); // Synchronize the new elements with pipeline state. If it's // paused limit the state change to pre-rolling. GstState state; gst_element_get_state(m_pipeline, &state, 0, 0); if (state < GST_STATE_PLAYING) state = GST_STATE_READY; gst_element_set_state(platformVideoSink, state); gst_element_set_state(videoScale, state); gst_element_set_state(colorspace, state); gst_element_set_state(queue, state); #ifndef GST_API_VERSION_1 // Query the current media segment informations and send them towards // the new tee branch downstream. GstQuery* query = gst_query_new_segment(GST_FORMAT_TIME); gboolean queryResult = gst_element_query(m_pipeline, query); if (!queryResult) { gst_query_unref(query); return true; } gint64 position; GstFormat format; if (!gst_element_query_position(m_pipeline, &format, &position)) position = 0; gdouble rate; gint64 startValue, stopValue; gst_query_parse_segment(query, &rate, &format, &startValue, &stopValue); GstEvent* event = gst_event_new_new_segment(FALSE, rate, format, startValue, stopValue, position); gst_pad_push_event(srcPad.get(), event); gst_query_unref(query); #endif return true; }
static void didReceiveWebViewMessageFromInjectedBundle(WebKitWebView* webView, const char* messageName, ImmutableDictionary& message) { if (g_str_equal(messageName, "DidInitiateLoadForResource")) { WebFrameProxy* frame = static_cast<WebFrameProxy*>(message.get(String::fromUTF8("Frame"))); API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); API::URLRequest* webRequest = static_cast<API::URLRequest*>(message.get(String::fromUTF8("Request"))); GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(webRequest->resourceRequest())); webkitWebViewResourceLoadStarted(webView, frame, resourceIdentifier->value(), request.get()); } else if (g_str_equal(messageName, "DidSendRequestForResource")) { API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier->value()); if (!resource) return; API::URLRequest* webRequest = static_cast<API::URLRequest*>(message.get(String::fromUTF8("Request"))); GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(webRequest->resourceRequest())); API::URLResponse* webRedirectResponse = static_cast<API::URLResponse*>(message.get(String::fromUTF8("RedirectResponse"))); GRefPtr<WebKitURIResponse> redirectResponse = webRedirectResponse ? adoptGRef(webkitURIResponseCreateForResourceResponse(webRedirectResponse->resourceResponse())) : 0; webkitWebResourceSentRequest(resource.get(), request.get(), redirectResponse.get()); } else if (g_str_equal(messageName, "DidReceiveResponseForResource")) { API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier->value()); if (!resource) return; API::URLResponse* webResponse = static_cast<API::URLResponse*>(message.get(String::fromUTF8("Response"))); GRefPtr<WebKitURIResponse> response = adoptGRef(webkitURIResponseCreateForResourceResponse(webResponse->resourceResponse())); webkitWebResourceSetResponse(resource.get(), response.get()); } else if (g_str_equal(messageName, "DidReceiveContentLengthForResource")) { API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier->value()); if (!resource) return; API::UInt64* contentLength = static_cast<API::UInt64*>(message.get(String::fromUTF8("ContentLength"))); webkitWebResourceNotifyProgress(resource.get(), contentLength->value()); } else if (g_str_equal(messageName, "DidFinishLoadForResource")) { API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier->value()); if (!resource) return; webkitWebResourceFinished(resource.get()); webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier->value()); } else if (g_str_equal(messageName, "DidFailLoadForResource")) { API::UInt64* resourceIdentifier = static_cast<API::UInt64*>(message.get(String::fromUTF8("Identifier"))); GRefPtr<WebKitWebResource> resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier->value()); if (!resource) return; API::Error* webError = static_cast<API::Error*>(message.get(String::fromUTF8("Error"))); const ResourceError& platformError = webError->platformError(); GUniquePtr<GError> resourceError(g_error_new_literal(g_quark_from_string(platformError.domain().utf8().data()), toWebKitError(platformError.errorCode()), platformError.localizedDescription().utf8().data())); webkitWebResourceFailed(resource.get(), resourceError.get()); webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier->value()); } else if (g_str_equal(messageName, "DidGetSnapshot")) { API::UInt64* callbackID = static_cast<API::UInt64*>(message.get("CallbackID")); WebImage* image = static_cast<WebImage*>(message.get("Snapshot")); webKitWebViewDidReceiveSnapshot(webView, callbackID->value(), image); } else ASSERT_NOT_REACHED(); }
static WKTypeRef getInjectedBundleInitializationUserData(WKContextRef, const void* clientInfo) { GRefPtr<GVariant> data = webkitWebContextInitializeWebExtensions(WEBKIT_WEB_CONTEXT(clientInfo)); GUniquePtr<gchar> dataString(g_variant_print(data.get(), TRUE)); return static_cast<WKTypeRef>(WKStringCreateWithUTF8CString(dataString.get())); }
unsigned MediaPlayerPrivateGStreamer::totalBytes() const { if (m_errorOccured) return 0; if (m_totalBytes != -1) return m_totalBytes; if (!m_source) return 0; GstFormat fmt = GST_FORMAT_BYTES; gint64 length = 0; #ifdef GST_API_VERSION_1 if (gst_element_query_duration(m_source.get(), fmt, &length)) { #else if (gst_element_query_duration(m_source.get(), &fmt, &length)) { #endif LOG_MEDIA_MESSAGE("totalBytes %" G_GINT64_FORMAT, length); m_totalBytes = static_cast<unsigned>(length); m_isStreaming = !length; return m_totalBytes; } // Fall back to querying the source pads manually. // See also https://bugzilla.gnome.org/show_bug.cgi?id=638749 GstIterator* iter = gst_element_iterate_src_pads(m_source.get()); bool done = false; while (!done) { #ifdef GST_API_VERSION_1 GValue item = G_VALUE_INIT; switch (gst_iterator_next(iter, &item)) { case GST_ITERATOR_OK: { GstPad* pad = static_cast<GstPad*>(g_value_get_object(&item)); gint64 padLength = 0; if (gst_pad_query_duration(pad, fmt, &padLength) && padLength > length) length = padLength; break; } #else gpointer data; switch (gst_iterator_next(iter, &data)) { case GST_ITERATOR_OK: { GRefPtr<GstPad> pad = adoptGRef(GST_PAD_CAST(data)); gint64 padLength = 0; if (gst_pad_query_duration(pad.get(), &fmt, &padLength) && padLength > length) length = padLength; break; } #endif case GST_ITERATOR_RESYNC: gst_iterator_resync(iter); break; case GST_ITERATOR_ERROR: // Fall through. case GST_ITERATOR_DONE: done = true; break; } #ifdef GST_API_VERSION_1 g_value_unset(&item); #endif } gst_iterator_free(iter); LOG_MEDIA_MESSAGE("totalBytes %" G_GINT64_FORMAT, length); m_totalBytes = static_cast<unsigned>(length); m_isStreaming = !length; return m_totalBytes; } void MediaPlayerPrivateGStreamer::updateAudioSink() { if (!m_playBin) return; GstElement* sinkPtr = 0; g_object_get(m_playBin.get(), "audio-sink", &sinkPtr, NULL); m_webkitAudioSink = adoptGRef(sinkPtr); } GstElement* MediaPlayerPrivateGStreamer::audioSink() const { return m_webkitAudioSink.get(); } void MediaPlayerPrivateGStreamer::sourceChanged() { GstElement* srcPtr = 0; g_object_get(m_playBin.get(), "source", &srcPtr, NULL); m_source = adoptGRef(srcPtr); if (WEBKIT_IS_WEB_SRC(m_source.get())) webKitWebSrcSetMediaPlayer(WEBKIT_WEB_SRC(m_source.get()), m_player); } void MediaPlayerPrivateGStreamer::cancelLoad() { if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded) return; if (m_playBin) gst_element_set_state(m_playBin.get(), GST_STATE_NULL); } void MediaPlayerPrivateGStreamer::updateStates() { if (!m_playBin) return; if (m_errorOccured) return; MediaPlayer::NetworkState oldNetworkState = m_networkState; MediaPlayer::ReadyState oldReadyState = m_readyState; GstState state; GstState pending; GstStateChangeReturn ret = gst_element_get_state(m_playBin.get(), &state, &pending, 250 * GST_NSECOND); bool shouldUpdateAfterSeek = false; switch (ret) { case GST_STATE_CHANGE_SUCCESS: LOG_MEDIA_MESSAGE("State: %s, pending: %s", gst_element_state_get_name(state), gst_element_state_get_name(pending)); m_resetPipeline = state <= GST_STATE_READY; // Try to figure out ready and network states. if (state == GST_STATE_READY) { m_readyState = MediaPlayer::HaveMetadata; m_networkState = MediaPlayer::Empty; // Cache the duration without emiting the durationchange // event because it's taken care of by the media element // in this precise case. if (!m_isEndReached) cacheDuration(); } else if ((state == GST_STATE_NULL) || (maxTimeLoaded() == duration())) { m_networkState = MediaPlayer::Loaded; m_readyState = MediaPlayer::HaveEnoughData; } else { m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData; m_networkState = MediaPlayer::Loading; } if (m_buffering && state != GST_STATE_READY) { m_readyState = MediaPlayer::HaveCurrentData; m_networkState = MediaPlayer::Loading; } // Now let's try to get the states in more detail using // information from GStreamer, while we sync states where // needed. if (state == GST_STATE_PAUSED) { if (!m_webkitAudioSink) updateAudioSink(); if (!m_volumeAndMuteInitialized) { notifyPlayerOfVolumeChange(); notifyPlayerOfMute(); m_volumeAndMuteInitialized = true; } if (m_buffering && m_bufferingPercentage == 100) { m_buffering = false; m_bufferingPercentage = 0; m_readyState = MediaPlayer::HaveEnoughData; LOG_MEDIA_MESSAGE("[Buffering] Complete."); if (!m_paused) { LOG_MEDIA_MESSAGE("[Buffering] Restarting playback."); gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING); } } else if (!m_buffering && (currentTime() < duration())) { m_paused = true; } } else if (state == GST_STATE_PLAYING) { m_readyState = MediaPlayer::HaveEnoughData; m_paused = false; if (m_buffering && !isLiveStream()) { m_readyState = MediaPlayer::HaveCurrentData; m_networkState = MediaPlayer::Loading; LOG_MEDIA_MESSAGE("[Buffering] Pausing stream for buffering."); gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED); } } else m_paused = true; // Is on-disk buffering in progress? if (m_fillTimer.isActive()) m_networkState = MediaPlayer::Loading; if (m_changingRate) { m_player->rateChanged(); m_changingRate = false; } if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; } break; case GST_STATE_CHANGE_ASYNC: LOG_MEDIA_MESSAGE("Async: State: %s, pending: %s", gst_element_state_get_name(state), gst_element_state_get_name(pending)); // Change in progress // On-disk buffering was attempted but the media is live. This // can't work so disable on-disk buffering and reset the // pipeline. if (state == GST_STATE_READY && isLiveStream() && m_preload == MediaPlayer::Auto) { setPreload(MediaPlayer::None); gst_element_set_state(m_playBin.get(), GST_STATE_NULL); gst_element_set_state(m_playBin.get(), GST_STATE_PAUSED); } // A live stream was paused, reset the pipeline. if (state == GST_STATE_PAUSED && pending == GST_STATE_PLAYING && isLiveStream()) { gst_element_set_state(m_playBin.get(), GST_STATE_NULL); gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING); } if (!isLiveStream() && !m_buffering) return; if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; } break; case GST_STATE_CHANGE_FAILURE: LOG_MEDIA_MESSAGE("Failure: State: %s, pending: %s", gst_element_state_get_name(state), gst_element_state_get_name(pending)); // Change failed return; case GST_STATE_CHANGE_NO_PREROLL: LOG_MEDIA_MESSAGE("No preroll: State: %s, pending: %s", gst_element_state_get_name(state), gst_element_state_get_name(pending)); if (state == GST_STATE_READY) m_readyState = MediaPlayer::HaveNothing; else if (state == GST_STATE_PAUSED) { m_readyState = MediaPlayer::HaveEnoughData; m_paused = true; // Live pipelines go in PAUSED without prerolling. m_isStreaming = true; } else if (state == GST_STATE_PLAYING) m_paused = false; if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; if (!m_paused) gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING); } else if (!m_paused) gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING); m_networkState = MediaPlayer::Loading; break; default: LOG_MEDIA_MESSAGE("Else : %d", ret); break; } if (seeking()) m_readyState = MediaPlayer::HaveNothing; if (shouldUpdateAfterSeek) timeChanged(); if (m_networkState != oldNetworkState) { LOG_MEDIA_MESSAGE("Network State Changed from %u to %u", oldNetworkState, m_networkState); m_player->networkStateChanged(); } if (m_readyState != oldReadyState) { LOG_MEDIA_MESSAGE("Ready State Changed from %u to %u", oldReadyState, m_readyState); m_player->readyStateChanged(); } } void MediaPlayerPrivateGStreamer::mediaLocationChanged(GstMessage* message) { if (m_mediaLocations) gst_structure_free(m_mediaLocations); const GstStructure* structure = gst_message_get_structure(message); if (structure) { // This structure can contain: // - both a new-location string and embedded locations structure // - or only a new-location string. m_mediaLocations = gst_structure_copy(structure); const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations"); if (locations) m_mediaLocationCurrentIndex = static_cast<int>(gst_value_list_get_size(locations)) -1; loadNextLocation(); } } bool MediaPlayerPrivateGStreamer::loadNextLocation() { if (!m_mediaLocations) return false; const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations"); const gchar* newLocation = 0; if (!locations) { // Fallback on new-location string. newLocation = gst_structure_get_string(m_mediaLocations, "new-location"); if (!newLocation) return false; } if (!newLocation) { if (m_mediaLocationCurrentIndex < 0) { m_mediaLocations = 0; return false; } const GValue* location = gst_value_list_get_value(locations, m_mediaLocationCurrentIndex); const GstStructure* structure = gst_value_get_structure(location); if (!structure) { m_mediaLocationCurrentIndex--; return false; } newLocation = gst_structure_get_string(structure, "new-location"); } if (newLocation) { // Found a candidate. new-location is not always an absolute url // though. We need to take the base of the current url and // append the value of new-location to it. KURL newUrl; if (gst_uri_is_valid(newLocation)) newUrl = KURL(KURL(), newLocation); else newUrl = KURL(KURL(), m_url.baseAsString() + newLocation); RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(m_url); if (securityOrigin->canRequest(newUrl)) { LOG_MEDIA_MESSAGE("New media url: %s", newUrl.string().utf8().data()); // Reset player states. m_networkState = MediaPlayer::Loading; m_player->networkStateChanged(); m_readyState = MediaPlayer::HaveNothing; m_player->readyStateChanged(); // Reset pipeline state. m_resetPipeline = true; gst_element_set_state(m_playBin.get(), GST_STATE_READY); GstState state; gst_element_get_state(m_playBin.get(), &state, 0, 0); if (state <= GST_STATE_READY) { // Set the new uri and start playing. setPlaybinURL(newUrl); gst_element_set_state(m_playBin.get(), GST_STATE_PLAYING); return true; } } } m_mediaLocationCurrentIndex--; return false; } void MediaPlayerPrivateGStreamer::loadStateChanged() { updateStates(); } void MediaPlayerPrivateGStreamer::timeChanged() { updateStates(); m_player->timeChanged(); }
static void testWebContextConfiguration(WebViewTest* test, gconstpointer) { WebKitWebsiteDataManager* manager = webkit_web_context_get_website_data_manager(test->m_webContext.get()); g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager)); test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(manager)); // Base directories are not used by TestMain. g_assert(!webkit_website_data_manager_get_base_data_directory(manager)); g_assert(!webkit_website_data_manager_get_base_cache_directory(manager)); GUniquePtr<char> localStorageDirectory(g_build_filename(Test::dataDirectory(), "local-storage", nullptr)); g_assert_cmpstr(localStorageDirectory.get(), ==, webkit_website_data_manager_get_local_storage_directory(manager)); g_assert(g_file_test(localStorageDirectory.get(), G_FILE_TEST_IS_DIR)); test->loadURI(kServer->getURIForPath("/empty").data()); test->waitUntilLoadFinished(); test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');", nullptr); GUniquePtr<char> indexedDBDirectory(g_build_filename(Test::dataDirectory(), "indexeddb", nullptr)); g_assert_cmpstr(indexedDBDirectory.get(), ==, webkit_website_data_manager_get_indexeddb_directory(manager)); g_assert(g_file_test(indexedDBDirectory.get(), G_FILE_TEST_IS_DIR)); test->loadURI(kServer->getURIForPath("/appcache").data()); test->waitUntilLoadFinished(); GUniquePtr<char> applicationCacheDirectory(g_build_filename(Test::dataDirectory(), "appcache", nullptr)); g_assert_cmpstr(applicationCacheDirectory.get(), ==, webkit_website_data_manager_get_offline_application_cache_directory(manager)); GUniquePtr<char> applicationCacheDatabase(g_build_filename(applicationCacheDirectory.get(), "ApplicationCache.db", nullptr)); unsigned triesCount = 4; while (!g_file_test(applicationCacheDatabase.get(), G_FILE_TEST_IS_REGULAR) && --triesCount) test->wait(0.25); g_assert(triesCount); GUniquePtr<char> webSQLDirectory(g_build_filename(Test::dataDirectory(), "websql", nullptr)); g_assert_cmpstr(webSQLDirectory.get(), ==, webkit_website_data_manager_get_websql_directory(manager)); test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);", nullptr); g_assert(g_file_test(webSQLDirectory.get(), G_FILE_TEST_IS_DIR)); GUniquePtr<char> diskCacheDirectory(g_build_filename(Test::dataDirectory(), "disk-cache", nullptr)); g_assert_cmpstr(diskCacheDirectory.get(), ==, webkit_website_data_manager_get_disk_cache_directory(manager)); g_assert(g_file_test(diskCacheDirectory.get(), G_FILE_TEST_IS_DIR)); // The default context should have a different manager with different configuration. WebKitWebsiteDataManager* defaultManager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default()); g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(defaultManager)); g_assert(manager != defaultManager); g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(manager), !=, webkit_website_data_manager_get_local_storage_directory(defaultManager)); g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(manager), !=, webkit_website_data_manager_get_indexeddb_directory(defaultManager)); g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(manager), !=, webkit_website_data_manager_get_disk_cache_directory(defaultManager)); g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(manager), !=, webkit_website_data_manager_get_offline_application_cache_directory(defaultManager)); g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(manager), !=, webkit_website_data_manager_get_websql_directory(defaultManager)); // Using Test::dataDirectory() we get the default configuration but for a differrent prefix. GRefPtr<WebKitWebsiteDataManager> baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(), nullptr)); g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(baseDataManager.get())); localStorageDirectory.reset(g_build_filename(Test::dataDirectory(), "localstorage", nullptr)); g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get()); indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", "indexeddb", nullptr)); g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get()); applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "applications", nullptr)); g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get()); webSQLDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", nullptr)); g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get()); g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory()); // Any specific configuration provided takes precedence over base dirs. indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomindexeddb", nullptr)); applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomappcache", nullptr)); baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(), "indexeddb-directory", indexedDBDirectory.get(), "offline-application-cache-directory", applicationCacheDirectory.get(), nullptr)); g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get()); g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get()); // The resutl should be the same as previous manager. g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get()); g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get()); g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory()); }
virtual bool runOpenPanel(WebPageProxy*, WebFrameProxy*, WebOpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener) override { GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkitFileChooserRequestCreate(parameters, listener)); webkitWebViewRunFileChooserRequest(m_webView, request.get()); return true; }
static void testWebContextSecurityFileXHR(WebViewTest* test, gconstpointer) { GUniquePtr<char> fileURL(g_strdup_printf("file://%s/simple.html", Test::getResourcesDir(Test::WebKit2Resources).data())); test->loadURI(fileURL.get()); test->waitUntilLoadFinished(); GUniquePtr<char> jsonURL(g_strdup_printf("file://%s/simple.json", Test::getResourcesDir().data())); GUniquePtr<char> xhr(g_strdup_printf("var xhr = new XMLHttpRequest; xhr.open(\"GET\", \"%s\"); xhr.send();", jsonURL.get())); WebKitJavascriptResult* consoleMessage = nullptr; webkit_user_content_manager_register_script_message_handler(test->m_userContentManager.get(), "console"); g_signal_connect(test->m_userContentManager.get(), "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), &consoleMessage); // By default file access is not allowed, this will show a console message with a cross-origin error. GUniqueOutPtr<GError> error; WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr()); g_assert(javascriptResult); g_assert(!error); g_assert(consoleMessage); GUniquePtr<char> messageString(WebViewTest::javascriptResultToCString(consoleMessage)); GRefPtr<GVariant> variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr); g_assert(variant.get()); unsigned level; const char* messageText; g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr); g_assert_cmpuint(level, ==, 3); // Console error message. GUniquePtr<char> expectedErrorMessage(g_strdup_printf("XMLHttpRequest cannot load %s. Cross origin requests are only supported for HTTP.", jsonURL.get())); g_assert_cmpstr(messageText, ==, expectedErrorMessage.get()); webkit_javascript_result_unref(consoleMessage); consoleMessage = nullptr; level = 0; messageText = nullptr; variant = nullptr; // Allow file access from file URLs. webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), TRUE); test->loadURI(fileURL.get()); test->waitUntilLoadFinished(); javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr()); g_assert(javascriptResult); g_assert(!error); // It isn't still possible to load file from an HTTP URL. test->loadURI(kServer->getURIForPath("/").data()); test->waitUntilLoadFinished(); javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr()); g_assert(javascriptResult); g_assert(!error); g_assert(consoleMessage); variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr); g_assert(variant.get()); g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr); g_assert_cmpuint(level, ==, 3); // Console error message. g_assert_cmpstr(messageText, ==, expectedErrorMessage.get()); webkit_javascript_result_unref(consoleMessage); g_signal_handlers_disconnect_matched(test->m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, &consoleMessage); webkit_user_content_manager_unregister_script_message_handler(test->m_userContentManager.get(), "console"); webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), FALSE); }
virtual PassRefPtr<WebPageProxy> createNewPage(WebPageProxy*, WebFrameProxy*, const WebCore::ResourceRequest& resourceRequest, const WebCore::WindowFeatures& windowFeatures, const NavigationActionData& navigationActionData) override { GRefPtr<WebKitURIRequest> request = adoptGRef(webkitURIRequestCreateForResourceRequest(resourceRequest)); WebKitNavigationAction navigationAction(request.get(), navigationActionData); return webkitWebViewCreateNewPage(m_webView, windowFeatures, &navigationAction); }
void NetworkStorageSession::getCredentialFromPersistentStorage(const ProtectionSpace& protectionSpace, Function<void (Credential&&)> completionHandler) { #if USE(LIBSECRET) if (m_sessionID.isEphemeral()) { completionHandler({ }); return; } const String& realm = protectionSpace.realm(); if (realm.isEmpty()) { completionHandler({ }); return; } GRefPtr<GHashTable> attributes = adoptGRef(secret_attributes_build(SECRET_SCHEMA_COMPAT_NETWORK, "domain", realm.utf8().data(), "server", protectionSpace.host().utf8().data(), "port", protectionSpace.port(), "protocol", schemeFromProtectionSpaceServerType(protectionSpace.serverType()), "authtype", authTypeFromProtectionSpaceAuthenticationScheme(protectionSpace.authenticationScheme()), nullptr)); if (!attributes) { completionHandler({ }); return; } m_persisentStorageCancellable = adoptGRef(g_cancellable_new()); m_persisentStorageCompletionHandler = WTFMove(completionHandler); secret_service_search(nullptr, SECRET_SCHEMA_COMPAT_NETWORK, attributes.get(), static_cast<SecretSearchFlags>(SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS), m_persisentStorageCancellable.get(), [](GObject* source, GAsyncResult* result, gpointer userData) { GUniqueOutPtr<GError> error; GUniquePtr<GList> elements(secret_service_search_finish(SECRET_SERVICE(source), result, &error.outPtr())); if (g_error_matches (error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; NetworkStorageSession* session = static_cast<NetworkStorageSession*>(userData); auto completionHandler = std::exchange(session->m_persisentStorageCompletionHandler, nullptr); if (error || !elements || !elements->data) { completionHandler({ }); return; } GRefPtr<SecretItem> secretItem = adoptGRef(static_cast<SecretItem*>(elements->data)); GRefPtr<GHashTable> attributes = adoptGRef(secret_item_get_attributes(secretItem.get())); String user = String::fromUTF8(static_cast<const char*>(g_hash_table_lookup(attributes.get(), "user"))); if (user.isEmpty()) { completionHandler({ }); return; } size_t length; GRefPtr<SecretValue> secretValue = adoptGRef(secret_item_get_secret(secretItem.get())); const char* passwordData = secret_value_get(secretValue.get(), &length); completionHandler(Credential(user, String::fromUTF8(passwordData, length), CredentialPersistencePermanent)); }, this); #else UNUSED_PARAM(protectionSpace); completionHandler({ }); #endif }
static GstFlowReturn webkitVideoSinkRender(GstBaseSink* baseSink, GstBuffer* buffer) { WebKitVideoSink* sink = WEBKIT_VIDEO_SINK(baseSink); WebKitVideoSinkPrivate* priv = sink->priv; g_mutex_lock(priv->bufferMutex); if (priv->unlocked) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; } #if USE(NATIVE_FULLSCREEN_VIDEO) // Ignore buffers if the video is already in fullscreen using // another sink. if (priv->gstGWorld->isFullscreen()) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; } #endif priv->buffer = gst_buffer_ref(buffer); #ifndef GST_API_VERSION_1 // For the unlikely case where the buffer has no caps, the caps // are implicitely the caps of the pad. This shouldn't happen. if (UNLIKELY(!GST_BUFFER_CAPS(buffer))) { buffer = priv->buffer = gst_buffer_make_metadata_writable(priv->buffer); gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(baseSink))); } GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(buffer); #else GRefPtr<GstCaps> caps; // The video info structure is valid only if the sink handled an allocation query. if (GST_VIDEO_INFO_FORMAT(&priv->info) != GST_VIDEO_FORMAT_UNKNOWN) caps = adoptGRef(gst_video_info_to_caps(&priv->info)); else caps = priv->currentCaps; #endif GstVideoFormat format; WebCore::IntSize size; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { gst_buffer_unref(buffer); g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't. // Here we convert to Cairo's ARGB. if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) { // Because GstBaseSink::render() only owns the buffer reference in the // method scope we can't use gst_buffer_make_writable() here. Also // The buffer content should not be changed here because the same buffer // could be passed multiple times to this method (in theory). GstBuffer* newBuffer = createGstBuffer(buffer); // Check if allocation failed. if (UNLIKELY(!newBuffer)) { g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } // We don't use Color::premultipliedARGBFromColor() here because // one function call per video pixel is just too expensive: // For 720p/PAL for example this means 1280*720*25=23040000 // function calls per second! #ifndef GST_API_VERSION_1 const guint8* source = GST_BUFFER_DATA(buffer); guint8* destination = GST_BUFFER_DATA(newBuffer); #else GstMapInfo sourceInfo; GstMapInfo destinationInfo; gst_buffer_map(buffer, &sourceInfo, GST_MAP_READ); const guint8* source = const_cast<guint8*>(sourceInfo.data); gst_buffer_map(newBuffer, &destinationInfo, GST_MAP_WRITE); guint8* destination = static_cast<guint8*>(destinationInfo.data); #endif for (int x = 0; x < size.height(); x++) { for (int y = 0; y < size.width(); y++) { #if G_BYTE_ORDER == G_LITTLE_ENDIAN unsigned short alpha = source[3]; destination[0] = (source[0] * alpha + 128) / 255; destination[1] = (source[1] * alpha + 128) / 255; destination[2] = (source[2] * alpha + 128) / 255; destination[3] = alpha; #else unsigned short alpha = source[0]; destination[0] = alpha; destination[1] = (source[1] * alpha + 128) / 255; destination[2] = (source[2] * alpha + 128) / 255; destination[3] = (source[3] * alpha + 128) / 255; #endif source += 4; destination += 4; } } #ifdef GST_API_VERSION_1 gst_buffer_unmap(buffer, &sourceInfo); gst_buffer_unmap(newBuffer, &destinationInfo); #endif gst_buffer_unref(buffer); buffer = priv->buffer = newBuffer; } // This should likely use a lower priority, but glib currently starves // lower priority sources. // See: https://bugzilla.gnome.org/show_bug.cgi?id=610830. priv->timeoutId = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, webkitVideoSinkTimeoutCallback, gst_object_ref(sink), reinterpret_cast<GDestroyNotify>(gst_object_unref)); g_cond_wait(priv->dataCondition, priv->bufferMutex); g_mutex_unlock(priv->bufferMutex); return GST_FLOW_OK; }
static void webKitWebAudioSrcConstructed(GObject* object) { WebKitWebAudioSrc* src = WEBKIT_WEB_AUDIO_SRC(object); WebKitWebAudioSourcePrivate* priv = src->priv; ASSERT(priv->bus); ASSERT(priv->provider); ASSERT(priv->sampleRate); priv->interleave = gst_element_factory_make("interleave", 0); priv->wavEncoder = gst_element_factory_make("wavenc", 0); if (!priv->interleave) { GST_ERROR_OBJECT(src, "Failed to create interleave"); return; } if (!priv->wavEncoder) { GST_ERROR_OBJECT(src, "Failed to create wavenc"); return; } gst_bin_add_many(GST_BIN(src), priv->interleave.get(), priv->wavEncoder.get(), NULL); gst_element_link_pads_full(priv->interleave.get(), "src", priv->wavEncoder.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); // For each channel of the bus create a new upstream branch for interleave, like: // queue ! capsfilter ! audioconvert. which is plugged to a new interleave request sinkpad. for (unsigned channelIndex = 0; channelIndex < priv->bus->numberOfChannels(); channelIndex++) { GstElement* queue = gst_element_factory_make("queue", 0); GstElement* capsfilter = gst_element_factory_make("capsfilter", 0); GstElement* audioconvert = gst_element_factory_make("audioconvert", 0); GRefPtr<GstCaps> monoCaps = adoptGRef(getGStreamerMonoAudioCaps(priv->sampleRate)); #ifdef GST_API_VERSION_1 GstAudioInfo info; gst_audio_info_from_caps(&info, monoCaps.get()); GST_AUDIO_INFO_POSITION(&info, 0) = webKitWebAudioGStreamerChannelPosition(channelIndex); GRefPtr<GstCaps> caps = adoptGRef(gst_audio_info_to_caps(&info)); g_object_set(capsfilter, "caps", caps.get(), NULL); #else g_object_set(capsfilter, "caps", monoCaps.get(), NULL); #endif // Configure the queue for minimal latency. g_object_set(queue, "max-size-buffers", static_cast<guint>(1), NULL); GstPad* pad = gst_element_get_static_pad(queue, "sink"); priv->pads = g_slist_prepend(priv->pads, pad); gst_bin_add_many(GST_BIN(src), queue, capsfilter, audioconvert, NULL); gst_element_link_pads_full(queue, "src", capsfilter, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(capsfilter, "src", audioconvert, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full(audioconvert, "src", priv->interleave.get(), 0, GST_PAD_LINK_CHECK_NOTHING); } priv->pads = g_slist_reverse(priv->pads); // wavenc's src pad is the only visible pad of our element. GRefPtr<GstPad> targetPad = adoptGRef(gst_element_get_static_pad(priv->wavEncoder.get(), "src")); gst_ghost_pad_set_target(GST_GHOST_PAD(priv->sourcePad), targetPad.get()); }
PassRefPtr<BitmapTexture> MediaPlayerPrivateGStreamerBase::updateTexture(TextureMapper* textureMapper) { g_mutex_lock(m_bufferMutex); if (!m_buffer) { g_mutex_unlock(m_bufferMutex); return 0; } const void* srcData = 0; #ifdef GST_API_VERSION_1 GRefPtr<GstCaps> caps = currentVideoSinkCaps(); #else GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(m_buffer); #endif if (!caps) { g_mutex_unlock(m_bufferMutex); return 0; } IntSize size; GstVideoFormat format; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { g_mutex_unlock(m_bufferMutex); return 0; } RefPtr<BitmapTexture> texture = textureMapper->acquireTextureFromPool(size); #if GST_CHECK_VERSION(1, 1, 0) GstVideoGLTextureUploadMeta* meta; if ((meta = gst_buffer_get_video_gl_texture_upload_meta(m_buffer))) { if (meta->n_textures == 1) { // BRGx & BGRA formats use only one texture. const BitmapTextureGL* textureGL = static_cast<const BitmapTextureGL*>(texture.get()); guint ids[4] = { textureGL->id(), 0, 0, 0 }; if (gst_video_gl_texture_upload_meta_upload(meta, ids)) { g_mutex_unlock(m_bufferMutex); return texture; } } } #endif #ifdef GST_API_VERSION_1 GstMapInfo srcInfo; gst_buffer_map(m_buffer, &srcInfo, GST_MAP_READ); srcData = srcInfo.data; #else srcData = GST_BUFFER_DATA(m_buffer); #endif texture->updateContents(srcData, WebCore::IntRect(WebCore::IntPoint(0, 0), size), WebCore::IntPoint(0, 0), stride, BitmapTexture::UpdateCannotModifyOriginalImageData); #ifdef GST_API_VERSION_1 gst_buffer_unmap(m_buffer, &srcInfo); #endif g_mutex_unlock(m_bufferMutex); return texture; }
virtual bool decidePolicyForUserMediaPermissionRequest(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin& securityOrigin, UserMediaPermissionRequestProxy& permissionRequest) override { GRefPtr<WebKitUserMediaPermissionRequest> userMediaPermissionRequest = adoptGRef(webkitUserMediaPermissionRequestCreate(permissionRequest, securityOrigin)); webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(userMediaPermissionRequest.get())); return true; }
// Returns the size of the video IntSize MediaPlayerPrivateGStreamerBase::naturalSize() const { if (!hasVideo()) return IntSize(); if (!m_videoSize.isEmpty()) return m_videoSize; #ifdef GST_API_VERSION_1 GRefPtr<GstCaps> caps = currentVideoSinkCaps(); #else g_mutex_lock(m_bufferMutex); GRefPtr<GstCaps> caps = m_buffer ? GST_BUFFER_CAPS(m_buffer) : 0; g_mutex_unlock(m_bufferMutex); #endif if (!caps) return IntSize(); // TODO: handle possible clean aperture data. See // https://bugzilla.gnome.org/show_bug.cgi?id=596571 // TODO: handle possible transformation matrix. See // https://bugzilla.gnome.org/show_bug.cgi?id=596326 // Get the video PAR and original size, if this fails the // video-sink has likely not yet negotiated its caps. int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; IntSize originalSize; GstVideoFormat format; if (!getVideoSizeAndFormatFromCaps(caps.get(), originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) return IntSize(); LOG_MEDIA_MESSAGE("Original video size: %dx%d", originalSize.width(), originalSize.height()); LOG_MEDIA_MESSAGE("Pixel aspect ratio: %d/%d", pixelAspectRatioNumerator, pixelAspectRatioDenominator); // Calculate DAR based on PAR and video size. int displayWidth = originalSize.width() * pixelAspectRatioNumerator; int displayHeight = originalSize.height() * pixelAspectRatioDenominator; // Divide display width and height by their GCD to avoid possible overflows. int displayAspectRatioGCD = greatestCommonDivisor(displayWidth, displayHeight); displayWidth /= displayAspectRatioGCD; displayHeight /= displayAspectRatioGCD; // Apply DAR to original video size. This is the same behavior as in xvimagesink's setcaps function. guint64 width = 0, height = 0; if (!(originalSize.height() % displayHeight)) { LOG_MEDIA_MESSAGE("Keeping video original height"); width = gst_util_uint64_scale_int(originalSize.height(), displayWidth, displayHeight); height = static_cast<guint64>(originalSize.height()); } else if (!(originalSize.width() % displayWidth)) { LOG_MEDIA_MESSAGE("Keeping video original width"); height = gst_util_uint64_scale_int(originalSize.width(), displayHeight, displayWidth); width = static_cast<guint64>(originalSize.width()); } else { LOG_MEDIA_MESSAGE("Approximating while keeping original video height"); width = gst_util_uint64_scale_int(originalSize.height(), displayWidth, displayHeight); height = static_cast<guint64>(originalSize.height()); } LOG_MEDIA_MESSAGE("Natural size: %" G_GUINT64_FORMAT "x%" G_GUINT64_FORMAT, width, height); m_videoSize = IntSize(static_cast<int>(width), static_cast<int>(height)); return m_videoSize; }
virtual bool decidePolicyForNotificationPermissionRequest(WebPageProxy*, API::SecurityOrigin*, NotificationPermissionRequest* permissionRequest) override { GRefPtr<WebKitNotificationPermissionRequest> notificationPermissionRequest = adoptGRef(webkitNotificationPermissionRequestCreate(permissionRequest)); webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(notificationPermissionRequest.get())); return true; }
static void testWebKitSettingsUserAgent(WebViewTest* test, gconstpointer) { GRefPtr<WebKitSettings> settings = adoptGRef(webkit_settings_new()); CString defaultUserAgent = webkit_settings_get_user_agent(settings.get()); webkit_web_view_set_settings(test->m_webView, settings.get()); g_assert(g_strstr_len(defaultUserAgent.data(), -1, "AppleWebKit")); g_assert(g_strstr_len(defaultUserAgent.data(), -1, "Safari")); webkit_settings_set_user_agent(settings.get(), 0); g_assert_cmpstr(defaultUserAgent.data(), ==, webkit_settings_get_user_agent(settings.get())); assertThatUserAgentIsSentInHeaders(test, defaultUserAgent.data()); webkit_settings_set_user_agent(settings.get(), ""); g_assert_cmpstr(defaultUserAgent.data(), ==, webkit_settings_get_user_agent(settings.get())); const char* funkyUserAgent = "Funky!"; webkit_settings_set_user_agent(settings.get(), funkyUserAgent); g_assert_cmpstr(funkyUserAgent, ==, webkit_settings_get_user_agent(settings.get())); assertThatUserAgentIsSentInHeaders(test, funkyUserAgent); webkit_settings_set_user_agent_with_application_details(settings.get(), "WebKitGTK+", 0); const char* userAgentWithNullVersion = webkit_settings_get_user_agent(settings.get()); g_assert_cmpstr(g_strstr_len(userAgentWithNullVersion, -1, defaultUserAgent.data()), ==, userAgentWithNullVersion); g_assert(g_strstr_len(userAgentWithNullVersion, -1, "WebKitGTK+")); webkit_settings_set_user_agent_with_application_details(settings.get(), "WebKitGTK+", ""); g_assert_cmpstr(webkit_settings_get_user_agent(settings.get()), ==, userAgentWithNullVersion); webkit_settings_set_user_agent_with_application_details(settings.get(), "WebCatGTK+", "3.4.5"); const char* newUserAgent = webkit_settings_get_user_agent(settings.get()); g_assert(g_strstr_len(newUserAgent, -1, "3.4.5")); g_assert(g_strstr_len(newUserAgent, -1, "WebCatGTK+")); GUniquePtr<char> applicationUserAgent(g_strdup_printf("%s %s", defaultUserAgent.data(), "WebCatGTK+/3.4.5")); g_assert_cmpstr(applicationUserAgent.get(), ==, webkit_settings_get_user_agent(settings.get())); }
bool PluginPackage::load() { if (m_isLoaded) { m_loadCount++; return true; } GOwnPtr<gchar> finalPath(g_strdup(m_path.utf8().data())); while (g_file_test(finalPath.get(), G_FILE_TEST_IS_SYMLINK)) { GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(finalPath.get())); GRefPtr<GFile> dir = adoptGRef(g_file_get_parent(file.get())); GOwnPtr<gchar> linkPath(g_file_read_link(finalPath.get(), 0)); GRefPtr<GFile> resolvedFile = adoptGRef(g_file_resolve_relative_path(dir.get(), linkPath.get())); finalPath.set(g_file_get_path(resolvedFile.get())); } // No joke. If there is a netscape component in the path, go back // to the symlink, as flash breaks otherwise. // See http://src.chromium.org/viewvc/chrome/trunk/src/webkit/glue/plugins/plugin_list_posix.cc GOwnPtr<gchar> baseName(g_path_get_basename(finalPath.get())); if (!g_strcmp0(baseName.get(), "libflashplayer.so") && g_strstr_len(finalPath.get(), -1, "/netscape/")) finalPath.set(g_strdup(m_path.utf8().data())); m_module = g_module_open(finalPath.get(), G_MODULE_BIND_LOCAL); if (!m_module) { LOG(Plugins,"Module Load Failed :%s, Error:%s\n", (m_path.utf8()).data(), g_module_error()); return false; } if (moduleMixesGtkSymbols(m_module)) { LOG(Plugins, "Ignoring module '%s' to avoid mixing GTK+ 2 and GTK+ 3 symbols.\n", m_path.utf8().data()); return false; } m_isLoaded = true; if (!g_strcmp0(baseName.get(), "libflashplayer.so")) { // Flash plugin can produce X errors that are handled by the GDK X error handler, which // exits the process. Since we don't want to crash due to flash bugs, we install a // custom error handler to show a warning when a X error happens without aborting. XSetErrorHandler(webkitgtkXError); } NP_InitializeFuncPtr NP_Initialize = 0; m_NPP_Shutdown = 0; NPError npErr; g_module_symbol(m_module, "NP_Initialize", (void**)&NP_Initialize); g_module_symbol(m_module, "NP_Shutdown", (void**)&m_NPP_Shutdown); if (!NP_Initialize || !m_NPP_Shutdown) goto abort; memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); m_pluginFuncs.size = sizeof(m_pluginFuncs); initializeBrowserFuncs(); npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); if (npErr != NPERR_NO_ERROR) goto abort; m_loadCount++; return true; abort: unloadWithoutShutdown(); return false; }
static void didReceiveURIRequest(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, WKPageRef initiatingPageRef, uint64_t requestID, const void* clientInfo) { WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(clientInfo); GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(webContext, toImpl(soupRequestManagerRef), toImpl(urlRef), toImpl(initiatingPageRef), requestID)); webkitWebContextReceivedURIRequest(webContext, request.get()); }
static void willSubmitForm(WKPageRef page, WKFrameRef frame, WKFrameRef sourceFrame, WKDictionaryRef values, WKTypeRef userData, WKFormSubmissionListenerRef listener, const void* clientInfo) { GRefPtr<WebKitFormSubmissionRequest> request = adoptGRef(webkitFormSubmissionRequestCreate(toImpl(values), toImpl(listener))); webkitWebViewSubmitFormRequest(WEBKIT_WEB_VIEW(clientInfo), request.get()); }