Build a Chrome Extension - Course for Beginners

  Рет қаралды 540,489

freeCodeCamp.org

freeCodeCamp.org

Күн бұрын

Learn how to create a Chrome browser extension using JavaScript and the new iteration of the web extensions platform, called Manifest V3.
✏️ Raman Hundal developed this tutorial.
💻 KZbin Bookmarker Starter Code: github.com/raman-at-pieces/yo...
💻 KZbin Bookmarker Finished Code: github.com/raman-at-pieces/yo...
🔗 Pieces Code Snippet Assistant download: pieces.app/install
🔗 Publishing extension on the chrome store docs: developer.chrome.com/docs/web...
⭐️ Course Contents ⭐️
⌨️ (0:00:00) Intro
⌨️ (0:02:15) Demo
⌨️ (0:05:18) Understanding manifest.json
⌨️ (0:08:46) Coding the extention
⌨️ (0:31:37) newVideoLoaded function
⌨️ (0:31:37) fetchBookmarks
⌨️ (0:37:08) addEventListener
⌨️ (0:48:03) addNewBookmark function
⌨️ (1:00:33) Testing the extention
🎉 Thanks to Pieces.app for providing a grant that made this course possible.
🎉 Thanks to our Champion and Sponsor supporters:
👾 Raymond Odero
👾 Agustín Kussrow
👾 aldo ferretti
👾 Otis Morgan
👾 DeezMaster
--
Learn to code for free and get a developer job: www.freecodecamp.org
Read hundreds of articles on programming: freecodecamp.org/news

Пікірлер: 365
@quiyoma3730
@quiyoma3730 2 жыл бұрын
Time to save to the PlayList of videos I wanna watch but will never watch
@noface00
@noface00 Жыл бұрын
way to go
@yochutes
@yochutes Жыл бұрын
😂
@maxfrischdev
@maxfrischdev Жыл бұрын
*cough cough* 😅🤣🤣🤣
@dimitrivasilev2905
@dimitrivasilev2905 Жыл бұрын
This one is only an hour long! I’m sure you can fit it in your schedule somewhere. I believe in you 💪
@boredomindex3353
@boredomindex3353 Жыл бұрын
😂
@sleeping_dragon
@sleeping_dragon 2 жыл бұрын
Definitely the best chrome extension tutorial I've seen so far. Others are either really outdated or don't teach much, or both. This is great.
@TypicallyThomas
@TypicallyThomas Жыл бұрын
If this is the best you've seen I worry about the others because this is quite poor
@bharathkumar5870
@bharathkumar5870 Жыл бұрын
@@TypicallyThomas plz tell me other sources for learning chrome extensions plz
@TypicallyThomas
@TypicallyThomas Жыл бұрын
@@bharathkumar5870 Don't have any I'm afraid
@zoldlen883
@zoldlen883 Жыл бұрын
@@TypicallyThomas You will need to go to school for it then. That's all the internet is. Follow alongs.
@dimitrivasilev2905
@dimitrivasilev2905 Жыл бұрын
@@zoldlen883 not sure how school is any better. School will introduce you to the concept of making a google chrome extension and then quiz you on it with the expectation that you’ve already mastered it.
@joeychukc
@joeychukc 3 ай бұрын
Thank you for making this useful video, this is so far the most detailed and advanced tutorial I could find on KZbin!
@harshjaiswal1634
@harshjaiswal1634 2 жыл бұрын
Exactly what I was looking for
@frodelius
@frodelius 2 жыл бұрын
@@anchyzas Well, does it work for you guys?
@pintaridergaming
@pintaridergaming 2 жыл бұрын
Ok this is crazy, i searched for this yesterday and now this came out
@aakarsh1475
@aakarsh1475 Жыл бұрын
Wow, this video is really advanced! He goes through all the steps so fast and assumes you already know a lot of things. This is definitely not for beginners who want to learn how to make an extension from scratch. You need some prior experience and knowledge to follow along. I wouldn't recommend this video to anyone who is just starting out with extensions. It might be too confusing and frustrating for them.
@nathanfoss766
@nathanfoss766 Жыл бұрын
He did say at the beginning of the video that you need an understanding of JavaScript and DOM manipulation.
@coryanders6328
@coryanders6328 10 ай бұрын
@@nathanfoss766 having plenty of experience with both, there are still a lot of other assumptions made about what the viewer knows. there's not even really a starting off point. it's kind of like "you know algebra, right? here's calc II".
@zabity
@zabity 7 ай бұрын
@@nathanfoss766 and then he skips the fact of using an IFEE as if it's obvious, then suddenly background.js comes in dunno why and then he puts an even listener on a chrome object in pure js. whoa!
@yuvrajsingh-gm6zk
@yuvrajsingh-gm6zk 2 ай бұрын
you gotta need to take the discomfort, learning isn't supposed to be fun, and whenever you find learning fun that is just because you have plenty of prior knowledge to begin with!
@edgyman1956
@edgyman1956 2 жыл бұрын
I've been looking for this course for so long
@frodelius
@frodelius 2 жыл бұрын
Keep looking.
@crusader_
@crusader_ 2 жыл бұрын
Low-key wanted this. Love free code camp
@BehruzbekOtayev
@BehruzbekOtayev 2 жыл бұрын
What's low-key?
@who_s_afraid
@who_s_afraid Жыл бұрын
​@@BehruzbekOtayev it says it has meaning of restrained, like “of low or moderate intensity, not very forceful" or chilly.
@eitan_schwartz
@eitan_schwartz 2 жыл бұрын
Waited for tutorial like this for long time
@dheerajrawat6201
@dheerajrawat6201 2 жыл бұрын
This is the thing i wanted from such a long time
@alexbright9849
@alexbright9849 2 жыл бұрын
This is what i did need yesterday and you posted this thanks❤️❤️❤️❤️❤️
@md.jannatulnayem4328
@md.jannatulnayem4328 Жыл бұрын
Absolutely loved it. Bring us part 2 ✨
@Neko-Pro-Watcher
@Neko-Pro-Watcher Жыл бұрын
Thank you. I learned a lot, this cover many things!
@chrisdesigns
@chrisdesigns 2 жыл бұрын
Freecode camp is incredible. One love❤️
@anonfourtyfive
@anonfourtyfive Жыл бұрын
Wow, just found out this. What a precious thing, I'll try this out.
@DogeMultiverse
@DogeMultiverse 2 жыл бұрын
learning thru the chrome extension discord is amazing!
@Qpham90
@Qpham90 11 ай бұрын
never would i have thought a delicious japanese noodle dish would teach me how to make a chrome extension, how far we've advanced
@kgarun
@kgarun Жыл бұрын
Great tutorial. Thanks!
@AbuFaizal
@AbuFaizal 2 жыл бұрын
love it, thanks for making this video
@universecode1101
@universecode1101 2 жыл бұрын
This is very cool, thanks guys 🤩
@gusr7513
@gusr7513 2 жыл бұрын
Hey everyone. If you add newVideoLoaded(); at the end of contentScript as the purposed quick fix, the extension won't work properly on reload. The reason is that you will not get the video ID into the currentVideo variable, so you won't be able to add new timestamps. The best quick fix I came up with was to force a new URL (I also studied how KZbin deals with different URLs) and I came up with this code that you can add to your contentScript in the place of newVideoLoaded() (the one at the end, line 64 of the finished code); let trail="&ytExt=ON"; if(!window.location.href.includes(trail)&&!window.location.href.includes("ab_channel")){ window.location.href+=trail; } This should force an update on the URL of the KZbin when necessary, which will then trigger the chrome.tabs.onUpdated. I hope this helps. (For those who want to know what is ab_channel, it is something youtube adds spontaneously for some videos (with channel info) and that triggers the chrome.tabs.onUpdated on its own.) Cheers! EDIT!! Also include a condition &&window.location.href.includes("youtube.com/watch") in the if statement i gave. You don't want it to update the URL in non-KZbin websites.
@ayomideoguntuase165
@ayomideoguntuase165 2 жыл бұрын
Admin should definitely pin this comment or help fix the github repo cos it fixed a major issue that renders the extension useless.
@IonutSultana
@IonutSultana Жыл бұрын
Thanks for helping us out. I was debugging this due to an "Extension context invalidated". That was generated because when calling the newVideoLoad() the fetchBookmarks function didn't have with what videoId to work with.
@OriginalCodeMaster
@OriginalCodeMaster 2 жыл бұрын
Nice tutorial, I was looking for such a video for a while. Thanks for your content 😍🤩
@Loug522
@Loug522 2 жыл бұрын
I've been learning js and html these past few days, this one seem like a fun adventure for when I finish the Scrimba course.
@jackepner9984
@jackepner9984 2 жыл бұрын
Came here BECAUSE of the Scrimba course... Scrimba is far better for gaining understanding of what javascript does and how to use it. But when it comes to a project... I was pretty disappointed to see the chrome extension project be nothing but a bookmark extension, which of course exists natively in all browsers. Useless. I'd at least like to spend my hours committed to a course building something that isn't completely worthless.
@benvarkey5097
@benvarkey5097 2 жыл бұрын
Was waiting ❤️
@viraatkumar8980
@viraatkumar8980 Жыл бұрын
anyone getting a failed to load resource error on the comleted version of the code from his github? says access it blocked by client or something
@patrickctaylor
@patrickctaylor 2 жыл бұрын
Thanks for the tutorial!
@popov654
@popov654 9 ай бұрын
Thanks for easy and understandable tutorial, it's really good. Though I would say some things could be done better. 1. You should probably test on timestamp existance on bookmark creation to avoid creating duplicates when a user clicks the button several times in a row 2. You should probably deal with storage in background page/service worker, and not in content script. Even though the code in content script will become less beautiful, I guess it is better in terms of architecture. And if you don't care about architecture at all, why just not move that to popup.js? Your content script really does not need to get access to the full bookmarks list in order to add a "plus" button and assign a click handler to it. 3. Maybe you don't have to refetch all the bookmarks after deletion, just add some logic for handling an empty list case (some speed optimization). 4. Finally, Chrome definitely won't allow us to change the active tab leaving the popup opened (though Firefox really allows something like this using a special development option to preserve all opened popups), but we can overprotect ourselves and save the current page url or video id somewhere in popup.js, so that we can be 100% sure that we are deleting the right things. I know that it is a video for beginners, but still. Also it was worth mentioning about the total storage limitsof each type that Chrome allows us to store.
@tunni8126
@tunni8126 Жыл бұрын
Two things I found useful while developing this extension: 1. choosing that video for test purposes which has no ads. Like those of sandeep maheshwari. 2. using 'extensions reloader' extension for one click reload of the upacked extensions. Make sure to pin this extension.
@Arunnn241
@Arunnn241 Жыл бұрын
Good video. By no means best video I've seen. It's clear there's a script or some background code that's being read from bc the order of operations from "what do I need to do" to "code I wrote" are out of order. You go through the instruction as if you're working from the solution rather than the problem and that eliminates the problem-solving process: questions like "why do I want left controls and not right controls?", "why this video player?", "why a value property?", "why are splitting this up into so many different functions from the start?" are prominent in a viewers' mind throughout the video which causes mental fatigue.
@ugur76
@ugur76 Жыл бұрын
This finished code itself in git repo is not working currently in chrome
@pranich
@pranich Жыл бұрын
Best tutorial. Thank you!
@briannaharris731
@briannaharris731 Жыл бұрын
What VScode extension are you using to provide autocomplete suggestions regarding the Chrome APIs as you code. Particularly in your background.js file?
@briannaharris731
@briannaharris731 Жыл бұрын
New to chrome development and any help would be much appreciated!
@tazimmahta7625
@tazimmahta7625 2 жыл бұрын
Yoo ! what a timing ❤❤❤
@graemeStanley
@graemeStanley Жыл бұрын
Great tutorial. Thanks for all your hard work putting this together.
@VitorHugo-np9qs
@VitorHugo-np9qs Жыл бұрын
Hey man, what's up? Can you put the extension created on video works?
@cabiste
@cabiste 9 ай бұрын
a better start to the video after the demo would've been to show us how to create the boilerplate code as that will let us understand how the extension works better
@adityasaurabhsingh6528
@adityasaurabhsingh6528 6 ай бұрын
use user snippet under the settings gear and there you can write your code ,change the name to boilerplate
@aM_Tovi
@aM_Tovi 4 ай бұрын
Thank you for this tutorial now i am going to make one extension for myself 😊
@edgargreene2628
@edgargreene2628 2 жыл бұрын
thx for this amazing tutorials
@sesencat
@sesencat Жыл бұрын
This inspire me to give up on coding
@ragtop63
@ragtop63 Жыл бұрын
I'd really like to see a thorough tutorial on how to build a browser extension using a framework, like Vue. Finding any information on how to do it seems to be one of the most difficult things to find on KZbin right now.
@user-un9ne9zw7d
@user-un9ne9zw7d Жыл бұрын
rightt? there are so many videos that talk about manifest version 2 but none on mv3
@popov654
@popov654 9 ай бұрын
@@user-un9ne9zw7d why the hell do I need MV3? I am more than happy with Manifest V2, service worker/content script/background page script are basically just all the same thing IMO.
@IndieLifeAlexAdamov
@IndieLifeAlexAdamov Жыл бұрын
Nice Tutorial. Made me realize I needed to brush up on Dom manipulation. Don
@ascourter
@ascourter Жыл бұрын
This is great. Thanks for sharing this. Is it best practice to aim for high compatibility when building extensions or do people include polyfills or other libraries like jquery when writing extensions?
@mikevaleriano9557
@mikevaleriano9557 Жыл бұрын
It's 2022, no one should be using jQuery for anything anymore.
@popov654
@popov654 9 ай бұрын
@@mikevaleriano9557 Why? jQuery is a good library in terms of wyntax, speed and compatibility.
@listerofsmeg
@listerofsmeg Жыл бұрын
It's broken background.js:1 Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
@sounakroy9284
@sounakroy9284 Жыл бұрын
yes
@gdp60b40
@gdp60b40 2 жыл бұрын
This is just amazing
@frodelius
@frodelius 2 жыл бұрын
Was it too good to be true after all?
@abdul_qadir7780
@abdul_qadir7780 Жыл бұрын
Woow i love the content. 😍
@jaiganesh12
@jaiganesh12 Жыл бұрын
Hey, great tutorial to get started with manifestv3 and chrome api.. You've got everything covered
@dota2content755
@dota2content755 10 ай бұрын
Helllo Im facing an error, when I send a message from background script I encounter this error, help me please I can't get rid of it....! Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
@plainzone8356
@plainzone8356 7 ай бұрын
same here
@Atomik-eb9jx
@Atomik-eb9jx 6 ай бұрын
Same here also, do you guys find any solutiion to this? @@plainzone8356
@miraclemark6120
@miraclemark6120 3 ай бұрын
Me 3
@vmendes9999
@vmendes9999 Жыл бұрын
Funtastic! Tank you Raman for this sharing I've created my first Chrome extension :-)
@BrandonCMaximum
@BrandonCMaximum 6 ай бұрын
I'm not sure if something has changed about Chrome extensions since this tutorial was made, but this doesn't seem to work anymore. Even the finished project in the git repo. After making my own changes to grab the URL on the content script/popup JS files directly instead of messing with utils and background, I finally got it working.
@dohverse1407
@dohverse1407 3 ай бұрын
Yes, it does not seem to be working for me either. Would you mind telling me what changes you made? Ive been having trouble fixing the problem. Thanks
@codingrich
@codingrich Жыл бұрын
at around 16:00 im getting an error because function newVideoLoaded() does not exist...i check the code and im still wondering. Why are you calling newVideoLoaded() when it is nowhere defined?
@sanjaykanade966
@sanjaykanade966 2 ай бұрын
After much research, selected this as my first tutorial on Chrome Extension Development. Turned out great! The only problem I faced initially was the error "Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist." Was not easy to find a solution. Finally, what worked is open a new Chrome window after reloading the extension. None of the solutions on Stack Overflow mentioned that. Another thing that should be made clearer in the video is how do you bring up the Console for the Background service worker. The video is too quick and it is difficult to see this part. Finally, turned out, you can do that from the Manage Extension itself. To see log of the Content script, use the regular browser Developer Tools.
@HavoJavo
@HavoJavo 2 жыл бұрын
I love you guys
@joeylucas7185
@joeylucas7185 2 жыл бұрын
Something I've wanted to do
@pastuh
@pastuh 2 жыл бұрын
Extensions helps when company programmers can't fast provide specific functions.
@mdhossen7082
@mdhossen7082 2 жыл бұрын
Wow,, this video is Very helpful,
@debillion
@debillion Жыл бұрын
Can you please, give me an understanding of how to automate the submission of this extension to webstore?
@syntheticperson
@syntheticperson Жыл бұрын
Extremely enlightening. Many thanks! 🙏🏽
@mrrishiraj88
@mrrishiraj88 2 жыл бұрын
Thanks a million
@RAVINDRAKUMAR-gj2nx
@RAVINDRAKUMAR-gj2nx Жыл бұрын
I am a beginner and just searched video on youtube to learn how extensions work and my doubt is cleared now. thank you a lot.
@UrzaRage778
@UrzaRage778 3 ай бұрын
Great video! How would you do something like grab all of the URLs from the tabs in the active window, and paste them to your clipboard with " " in-between each URL?
@preadsy6912
@preadsy6912 2 жыл бұрын
Very interesting!! This course is really exciting and modernistic
@eab4984
@eab4984 Жыл бұрын
In my addNewBookmarkEventHandler the line currentVideoBookmarks = await fetchBookmarks(); throws an error with the message: Uncaught TypeError: Cannot read properties of undefined (reading 'sync') at :3:26 at new Promise () at fetchBookmarks (:2:16) at :1:31 What could that be?
@mbdAli
@mbdAli Жыл бұрын
this one saved me ton of time. how to get pagesource of new window opened?
@josemontalvo5052
@josemontalvo5052 Жыл бұрын
How would you go about doing the following: When you click on the icon to bookmark, the extension popup opens automatically? no need for you to go all the way to the icon and click it?
@shruthimohan8438
@shruthimohan8438 Жыл бұрын
hi....did you get solution to this prb?
@m-108
@m-108 10 ай бұрын
i want to make a chrome extension in which i can freely zoom in x-axis or y-axis of a website independently or individually. specifically, i am currently unsatisfied with the UI of g-calendar and thus want to vertically zoom in on the page without horizontally zooming in. i hope such type of chrome extension can be made, isn't it?
@suniljadaun5814
@suniljadaun5814 2 жыл бұрын
Arrre bhartiya ... feel proud
@fareedezzedeen8017
@fareedezzedeen8017 Жыл бұрын
I was looking for this for a long time, All contents talks about v2
@alexandr8151
@alexandr8151 11 ай бұрын
Awesome!!
@robimegu3712
@robimegu3712 7 ай бұрын
It does not works for me... even if I just cloning the full version (youtube-bookmarker-finished-code) It gives me strange errors what I cannot fix... if I click on plus it does not do anything... does not add any bookmarks to the popup
@nocopyrightgameplaystockvi231
@nocopyrightgameplaystockvi231 2 жыл бұрын
I am going to develop a pdf maker for the code in the webIDE.
@firewatermoonsun
@firewatermoonsun Жыл бұрын
Many thanks!))
@TipsJazzInferno
@TipsJazzInferno 2 жыл бұрын
First Comment Thank you mcuh great
@shreedharpandey3319
@shreedharpandey3319 2 жыл бұрын
This is gonna make me some good money.
@SlLakshan
@SlLakshan 11 ай бұрын
Thank You 💗💓
@arunprashanth369
@arunprashanth369 11 ай бұрын
what chrome extension i want to create a extension through which i can place buy sell orders while i am doing analysis in the tradingview charting website with a 3 sec timer to cancel (optional) and also info about the position i have taken, without switchin logging moving too much . well need to figure it out how to do it just started the course so hopefully built it in 30 days
@cu0ngpitt
@cu0ngpitt 2 жыл бұрын
why do you write the content script in a immediately invoked function?
@Praveenkumar-gv2qu
@Praveenkumar-gv2qu 2 жыл бұрын
Awesome ❤️
@JoaquinPeMM
@JoaquinPeMM Ай бұрын
Would anyone mind to explain me the syntax on the "chrome.storage.sync.get([currentVideo], (obj) => {..." inside the fetchBookmarks function? is [currentVideo] the name of the key?
@ericstudiox7226
@ericstudiox7226 Жыл бұрын
this is a beginners question im sure but when i click on loadunpack, it doesn't see any of my files which i created in dreamweaver..ie js,json,css,html , nothing...help please
@changxinzhang
@changxinzhang Жыл бұрын
why I can only see the console.log of contentScript using Inspect? I cannot see the console.log of background.js
@clearthinking5441
@clearthinking5441 6 ай бұрын
What is the difference going to be between a (Chrome Extension + ChatGPT) and GPTStore?
@MadaniChannel_QuranUrdu
@MadaniChannel_QuranUrdu 2 жыл бұрын
Masha'Allah 🌹
@jayarcher3052
@jayarcher3052 10 ай бұрын
If anyone is having issues getting test logs to display, or undefined such as at 17:33, I have found that you need to load a new youtube video. at least on my machine simply reloading does nothing and will not alert the extension to begin doing anything.
@nitinnagar4863
@nitinnagar4863 9 ай бұрын
you saved me
@kh0lis
@kh0lis 8 ай бұрын
but I don't see "URLSearchParams" in console tab
@littlehearts7039
@littlehearts7039 Жыл бұрын
Thanks Ramen
@kintag4459
@kintag4459 2 жыл бұрын
Thank you M.r
@05060024
@05060024 Жыл бұрын
Why did "async" suddenly appear on line 14 at 24:34? There's no explanation of that.
@shivkini9119
@shivkini9119 Жыл бұрын
When I use it on videos which are segmented, the button becomes very narrow. How to avoid this?
@juggla4evr1
@juggla4evr1 Жыл бұрын
How can I have someone build Me an extension & at the same time a website, would they be two different things or can You do them at the same time? What's the recommended method?
@shanli9593
@shanli9593 Жыл бұрын
how to debug during development if things don't work out as expected?
@user-ez6dn5do9p
@user-ez6dn5do9p 2 ай бұрын
I want to create an extension that downloads chatgpt response in pdf file. Additional features may include enabling user save pdf to preffered place of choice in preffered document type e.g. word instead of pdf
@user-ig2kn5xd9m
@user-ig2kn5xd9m 5 ай бұрын
I want to build an extension like autods. How would I go about in doing that ? It's a product importing tool.
@imaditya01
@imaditya01 2 жыл бұрын
Gonna watch da whole thing. Who is stayin with me?
@user-zz7hn5py2x
@user-zz7hn5py2x 11 ай бұрын
more videos in this play list pleas
@chrisklupenger4999
@chrisklupenger4999 Жыл бұрын
what text editor is he using for the coding?
@894359
@894359 2 жыл бұрын
I tried my 1st extension a few months ago and could never figure out how to call a global function in the web app and pass some parameters from the extension to it? I even hired someone from a website to help and they couldn't do it! I gave up!
@sunnyy6295
@sunnyy6295 8 ай бұрын
will it work in safari browser as well?
@AbhijeetBGavali
@AbhijeetBGavali 2 жыл бұрын
use this to list your idea for the new extension, let's see who comes up with the best idea!
@AsianServer
@AsianServer 2 жыл бұрын
Plse make video on full stack web development in one video which is longer like more than 30 hours and cover popular framework and libraries. Plese make a video
@dzienisz
@dzienisz 7 ай бұрын
9:25 Please explain the use of IIFE. Is it necessary?
@AhmedAbdRapoA
@AhmedAbdRapoA Жыл бұрын
Something is missing here How do the extension is being updated on the flay? You didn't even mention that part.
@shuhaozhang7332
@shuhaozhang7332 Жыл бұрын
Got the error "Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist" background.js line 1
@atulya3344
@atulya3344 Жыл бұрын
did you get the resolution for it ?
@riyadutta2282
@riyadutta2282 Жыл бұрын
@@atulya3344 try adding this in background.js chrome.runtime.onConnect.addListener(function(port) { port.onMessage.addListener(function(msg) { port.postMessage({counter: msg.counter+1}); }); });
@atulya3344
@atulya3344 Жыл бұрын
@@riyadutta2282 Thanks much, but i found that, my content scripts was not loading, thus I used insertScript to add it and then I was able to run it
@riyadutta2282
@riyadutta2282 Жыл бұрын
@@atulya3344 can you share the code that helped you in running that... Actually I'm facing little problem.. this extension isn't working properly..
@atulya3344
@atulya3344 Жыл бұрын
@@riyadutta2282 sure, will share soon. Indeed I have not created this extension but only I picked the calling mechanism
1❤️#thankyou #shorts
00:21
あみか部
Рет қаралды 47 МЛН
1❤️#thankyou #shorts
00:21
あみか部
Рет қаралды 47 МЛН