Skip to content

Commit

Permalink
Merge pull request bigbluebutton#191 from joshua-arts/html5-support
Browse files Browse the repository at this point in the history
Add support for HTML5 client
  • Loading branch information
Joshua Arts authored Oct 12, 2017
2 parents bca906f + 1644358 commit 3b32a92
Show file tree
Hide file tree
Showing 19 changed files with 223 additions and 74 deletions.
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,6 @@ gem 'yt', '~> 0.28.0'

# Simple HTTP client.
gem 'faraday'

# For device detection to determine BigBlueButton client.
gem 'browser'
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ GEM
sass (~> 3.2)
bootstrap-social-rails (4.12.0)
railties (>= 3.1)
browser (2.5.1)
builder (3.2.3)
byebug (9.0.6)
climate_control (0.2.0)
Expand Down Expand Up @@ -279,6 +280,7 @@ DEPENDENCIES
bigbluebutton-api-ruby
bootstrap-sass (= 3.3.0.0)
bootstrap-social-rails (~> 4.12)
browser
byebug
coffee-rails (~> 4.2)
dotenv-rails
Expand Down
4 changes: 2 additions & 2 deletions app/assets/javascripts/active_meetings.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ var initialPopulate = function(){

// Populate waiting meetings.
Object.keys(data['waiting']).forEach(function(key) {
WAITING[name] = {'name': key, 'users': data['waiting'][key]}
updateMeetingText(WAITING[name])
WAITING[key] = {'name': key, 'users': data['waiting'][key]}
updateMeetingText(WAITING[key])
})

// Add the meetings to the active meetings list.
Expand Down
2 changes: 2 additions & 0 deletions app/assets/javascripts/channels/meeting_updates.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
body: I18n.user_waiting_body.replace(/%{user}/, data.user).replace(/%{meeting}/, '"'+data.meeting_name+'"')
});
}
} else if(data.action === 'unable_to_join') {
showAlert(I18n.unable_to_join_mobile, 6000)
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/landing.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
jqxhr.done(function(data) {
if (data.messageKey === 'wait_for_moderator') {
waitForModerator(Meeting.getInstance().getURL());
} else {
} else if (data.messageKey === 'ok') {
$(location).attr("href", data.response.join_url);
}
});
Expand Down
3 changes: 2 additions & 1 deletion app/assets/javascripts/shared.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ var showNotification = function(title, options) {
if (Notification.permission === "granted") {
var icon = '<%= asset_path("bbb-logo.png") %>';
options = $.extend(options, {
icon: icon
icon: icon,
tag: 'UserWaiting'
});
var notification = new Notification(title, options);
notification.onclick = function() {
Expand Down
5 changes: 4 additions & 1 deletion app/controllers/bbb_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ def join
if bbb_res[:returncode] && current_user == user
JoinMeetingJob.perform_later(user, params[:id], base_url)
WaitingList.empty(options[:room_owner], options[:meeting_name])
# user will be waiting for a moderator
# the user can't join because they are on mobile and HTML5 is not enabled.
elsif bbb_res[:messageKey] == 'unable_to_join'
NotifyUserCantJoinJob.perform_later(user.encrypted_id, params[:id], params[:name])
# user will be waiting for a moderator
else
NotifyUserWaitingJob.perform_later(user.encrypted_id, params[:id], params[:name])
end
Expand Down
18 changes: 12 additions & 6 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@ class UsersController < ActionController::Base
# For updating a users background image.
def update

# Make sure they actually select a file.
if params[:user] then
if params[:commit] == t('upload')
# Make sure they actually select a file.
if params[:user] then
@user = User.find(params[:id])
@user.assign_attributes(background: user_params[:background])
flash[:danger] = t('invalid_file') unless @user.save
else
flash[:danger] = t('no_file')
end
elsif params[:commit] == t('switch_clients')
# Switch the users default client.
@user = User.find(params[:id])
@user.assign_attributes(background: user_params[:background])
flash[:danger] = t('invalid_file') unless @user.save
else
flash[:danger] = t('no_file')
@user.update_attributes(use_html5: !@user.use_html5)
end

# Reload the page to apply changes and show flash messages.
Expand Down
4 changes: 4 additions & 0 deletions app/helpers/landing_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@

module LandingHelper

def html5_enabled?
Rails.configuration.html5_enabled
end

end
24 changes: 24 additions & 0 deletions app/jobs/notify_user_cant_join_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2016 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

class NotifyUserCantJoinJob < ApplicationJob
queue_as :default

def perform(room, meeting, user)
payload = { action: 'unable_to_join', user: user, meeting_name: meeting }
ActionCable.server.broadcast "#{room}-#{meeting}_meeting_updates_channel", payload
end
end
159 changes: 103 additions & 56 deletions app/lib/bbb_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,71 +53,109 @@ def bbb_join_url(meeting_token, full_name, options={})
if !bbb
return call_invalid_res
else
meeting_id = bbb_meeting_id(meeting_token)
# Verify HTML5 is running.
html5_running = Rails.configuration.html5_enabled

# Determine if the user is on mobile.
browser = Browser.new(request.user_agent)
mobile = browser.device.tablet?

# If the user is on mobile and the BigBlueButton server isn't running the HTML5 client,
# they can't join or create meetings.
if mobile and !html5_running then
return unable_to_join_res
else
meeting_id = bbb_meeting_id(meeting_token)

# See if the meeting is running
begin
bbb_meeting_info = bbb.get_meeting_info(meeting_id, nil)
rescue BigBlueButton::BigBlueButtonException => exc
# This means that is not created
# See if the meeting is running
begin
bbb_meeting_info = bbb.get_meeting_info(meeting_id, nil)
rescue BigBlueButton::BigBlueButtonException => exc
# This means that is not created

if options[:wait_for_moderator] && !options[:user_is_moderator]
return wait_moderator_res
end

logger.info "Message for the log file #{exc.key}: #{exc.message}"

# Prepare parameters for create
logout_url = options[:meeting_logout_url] || "#{request.base_url}"
moderator_password = random_password(12)
viewer_password = random_password(12)
meeting_options = {
record: options[:meeting_recorded].to_s,
logoutURL: logout_url,
moderatorPW: moderator_password,
attendeePW: viewer_password,
moderatorOnlyMessage: options[:moderator_message],
"meta_#{BbbApi::META_LISTED}": false,
"meta_#{BbbApi::META_TOKEN}": meeting_token
}

meeting_options.merge!(
{ "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] }
) if options[:hook_url]

# these parameters are used to filter recordings by room and meeting
meeting_options.merge!(
{ "meta_room-id": options[:room_owner],
"meta_meeting-name": options[:meeting_name]}
) if options[:room_owner]

# Only register webhooks if they are enabled it's not a guest meeting.
if Rails.configuration.use_webhooks && params[:resource] == 'rooms'
webhook_register(options[:hook_url], meeting_id)
end

# Create the meeting
begin
bbb.create_meeting(options[:meeting_name], meeting_id, meeting_options)
rescue BigBlueButton::BigBlueButtonException => exc
logger.info "BBB error on create #{exc.key}: #{exc.message}"
end

# And then get meeting info
bbb_meeting_info = bbb.get_meeting_info( meeting_id, nil )
end

if options[:wait_for_moderator] && !options[:user_is_moderator]
if options[:wait_for_moderator] && !options[:user_is_moderator] && bbb_meeting_info[:moderatorCount] <= 0
return wait_moderator_res
end

logger.info "Message for the log file #{exc.key}: #{exc.message}"

# Prepare parameters for create
logout_url = options[:meeting_logout_url] || "#{request.base_url}"
moderator_password = random_password(12)
viewer_password = random_password(12)
meeting_options = {
record: options[:meeting_recorded].to_s,
logoutURL: logout_url,
moderatorPW: moderator_password,
attendeePW: viewer_password,
moderatorOnlyMessage: options[:moderator_message],
"meta_#{BbbApi::META_LISTED}": false,
"meta_#{BbbApi::META_TOKEN}": meeting_token
}
meeting_options.merge!(
{ "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] }
) if options[:hook_url]

# these parameters are used to filter recordings by room and meeting
meeting_options.merge!(
{ "meta_room-id": options[:room_owner],
"meta_meeting-name": options[:meeting_name]}
) if options[:room_owner]

# Only register webhooks if they are enabled it's not a guest meeting.
if Rails.configuration.use_webhooks && params[:resource] == 'rooms'
webhook_register(options[:hook_url], meeting_id)
# Get the join url
if (options[:user_is_moderator])
password = bbb_meeting_info[:moderatorPW]
else
password = bbb_meeting_info[:attendeePW]
end

# Create the meeting
begin
bbb.create_meeting(options[:meeting_name], meeting_id, meeting_options)
rescue BigBlueButton::BigBlueButtonException => exc
logger.info "BBB error on create #{exc.key}: #{exc.message}"

# Determine which client to join as.
if current_user.nil?
use_html5 = Rails.configuration.use_html5_by_default
else
use_html5 = current_user.use_html5
end

# Restrict client if needed.
if mobile && html5_running
# Must use HTML5 because they are on mobile.
use_html5 = true
elsif !mobile && !html5_running
# HTML5 is not running, so must use Flash.
use_html5 = false
end

# Generate the join URL.
if use_html5
clientURL = bbb_endpoint.gsub('bigbluebutton/', 'html5client/join')
join_url = bbb.join_meeting_url(meeting_id, full_name, password, {clientURL: clientURL})
else
join_url = bbb.join_meeting_url(meeting_id, full_name, password)
end

# And then get meeting info
bbb_meeting_info = bbb.get_meeting_info( meeting_id, nil )
end

if options[:wait_for_moderator] && !options[:user_is_moderator] && bbb_meeting_info[:moderatorCount] <= 0
return wait_moderator_res
end

# Get the join url
if (options[:user_is_moderator])
password = bbb_meeting_info[:moderatorPW]
else
password = bbb_meeting_info[:attendeePW]
return success_join_res(join_url)
end
join_url = bbb.join_meeting_url(meeting_id, full_name, password )
return success_join_res(join_url)
end
end

Expand Down Expand Up @@ -300,6 +338,15 @@ def success_join_res(join_url)
}
}
end

def unable_to_join_res
{
returncode: false,
messageKey: "unable_to_join",
message: "Unable to join.",
status: :ok
}
end

def wait_moderator_res
{
Expand Down
13 changes: 13 additions & 0 deletions app/views/landing/preferences.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

<% if @user %>
<div class="upload-form">
<h3><%= t('background_image') %></h3>
<p> <%= t('background_image') + ": " + (@user.background_file_name || '') %> </p>
<%= form_for @user, :html => { :multipart => true } do |f| %>
<div class="form-group">
Expand All @@ -31,6 +32,18 @@
<%= f.submit t('upload'), class: 'btn btn-info' %>
<% end %>
</div>
<br>
<div class="html5-check">
<h3><%= t('prefered_client') %></h3>
<% if html5_enabled? %>
<p><%= t('currently_joining_with', client: @user.use_html5 ? t('client_html5') : t('client_flash')) %></p>
<%= form_for @user do |f| %>
<%= f.submit t('switch_clients'), class: 'btn btn-info' %>
<% end %>
<% else %>
<p><%= t('html5_not_enabled') %></p>
<% end %>
</div>
<% else %>
<h3><%= t('preferences_logged') %></h3>
<% end %>
Expand Down
1 change: 1 addition & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Application < Rails::Application
config.disable_guest_access = ENV['DISABLE_GUEST_ACCESS'] && ENV['DISABLE_GUEST_ACCESS'] == "true"
config.enable_youtube_uploading = ENV['ENABLE_YOUTUBE_UPLOADING'] && ENV['ENABLE_YOUTUBE_UPLOADING'] == "true"
config.enable_qrcode_generation = ENV['ENABLE_QRCODE_GENERATION'] && ENV['ENABLE_QRCODE_GENERATION'] == "true"
config.use_html5_by_default = ENV['USE_HTML5_BY_DEFAULT'] == "true"

# SMTP and action mailer
if config.mail_notifications
Expand Down
19 changes: 19 additions & 0 deletions config/initializers/html5_client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2016 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

# Send a request to check if the HTML5 client is enabled on the BigBlueButton server.
res = Faraday.get(Rails.configuration.bigbluebutton_endpoint.gsub('bigbluebutton/', 'html5client/check'))
Rails.application.config.html5_enabled = res.status == 200
Loading

0 comments on commit 3b32a92

Please sign in to comment.